Convert gv2 update messages to backup distinct protos.
This commit is contained in:
parent
0036b8e2d6
commit
98865d61dd
15 changed files with 1019 additions and 81 deletions
|
@ -118,7 +118,8 @@ class ConversationElementGenerator {
|
|||
null,
|
||||
null,
|
||||
0,
|
||||
false
|
||||
false,
|
||||
null
|
||||
)
|
||||
|
||||
val conversationMessage = ConversationMessageFactory.createWithUnresolvedData(
|
||||
|
|
|
@ -84,7 +84,12 @@ abstract class ConversationListDataSource implements PagedDataSource<Long, Conve
|
|||
if (!MessageTypes.isGroupV2(record.getType())) {
|
||||
needsResolve.add(record.getRecipient().getId());
|
||||
} else if (MessageTypes.isGroupUpdate(record.getType())) {
|
||||
UpdateDescription description = MessageRecord.getGv2ChangeDescription(ApplicationDependencies.getApplication(), record.getBody(), null);
|
||||
UpdateDescription description;
|
||||
if (record.getMessageExtras() != null) {
|
||||
description = MessageRecord.getGv2ChangeDescription(ApplicationDependencies.getApplication(), record.getMessageExtras(), null);
|
||||
} else {
|
||||
description = MessageRecord.getGv2ChangeDescription(ApplicationDependencies.getApplication(), record.getBody(), null);
|
||||
}
|
||||
needsResolve.addAll(description.getMentioned().stream().map(RecipientId::from).collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -572,7 +572,11 @@ public final class ConversationListItem extends ConstraintLayout implements Bind
|
|||
}
|
||||
} else if (MessageTypes.isGroupUpdate(thread.getType())) {
|
||||
if (thread.getRecipient().isPushV2Group()) {
|
||||
if (thread.getMessageExtras() != null) {
|
||||
return emphasisAdded(context, MessageRecord.getGv2ChangeDescription(context, thread.getMessageExtras(), null), defaultTint);
|
||||
} else {
|
||||
return emphasisAdded(context, MessageRecord.getGv2ChangeDescription(context, thread.getBody(), null), defaultTint);
|
||||
}
|
||||
} else {
|
||||
return emphasisAdded(context, context.getString(R.string.ThreadRecord_group_updated), R.drawable.ic_update_group_16, defaultTint);
|
||||
}
|
||||
|
|
|
@ -108,6 +108,7 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList
|
|||
import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GroupCallUpdateDetails
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.MessageExportState
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.MessageExtras
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ProfileChangeDetails
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.SessionSwitchoverEvent
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ThreadMergeEvent
|
||||
|
@ -207,6 +208,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||
const val LATEST_REVISION_ID = "latest_revision_id"
|
||||
const val ORIGINAL_MESSAGE_ID = "original_message_id"
|
||||
const val REVISION_NUMBER = "revision_number"
|
||||
const val MESSAGE_EXTRAS = "message_extras"
|
||||
|
||||
const val QUOTE_NOT_PRESENT_ID = 0L
|
||||
const val QUOTE_TARGET_MISSING_ID = -1L
|
||||
|
@ -264,7 +266,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||
$SCHEDULED_DATE INTEGER DEFAULT -1,
|
||||
$LATEST_REVISION_ID INTEGER DEFAULT NULL REFERENCES $TABLE_NAME ($ID) ON DELETE CASCADE,
|
||||
$ORIGINAL_MESSAGE_ID INTEGER DEFAULT NULL REFERENCES $TABLE_NAME ($ID) ON DELETE CASCADE,
|
||||
$REVISION_NUMBER INTEGER DEFAULT 0
|
||||
$REVISION_NUMBER INTEGER DEFAULT 0,
|
||||
$MESSAGE_EXTRAS BLOB DEFAULT NULL
|
||||
)
|
||||
"""
|
||||
|
||||
|
@ -343,7 +346,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||
SCHEDULED_DATE,
|
||||
LATEST_REVISION_ID,
|
||||
ORIGINAL_MESSAGE_ID,
|
||||
REVISION_NUMBER
|
||||
REVISION_NUMBER,
|
||||
MESSAGE_EXTRAS
|
||||
)
|
||||
|
||||
private val MMS_PROJECTION: Array<String> = MMS_PROJECTION_BASE + "NULL AS ${AttachmentTable.ATTACHMENT_JSON_ALIAS}"
|
||||
|
@ -4985,6 +4989,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||
val originalMessageId: MessageId? = cursor.requireLong(ORIGINAL_MESSAGE_ID).let { if (it == 0L) null else MessageId(it) }
|
||||
val editCount = cursor.requireInt(REVISION_NUMBER)
|
||||
val isRead = cursor.requireBoolean(READ)
|
||||
val messageExtraBytes = cursor.requireBlob(MESSAGE_EXTRAS)
|
||||
val messageExtras = if (messageExtraBytes != null) MessageExtras.ADAPTER.decode(messageExtraBytes) else null
|
||||
|
||||
if (!TextSecurePreferences.isReadReceiptsEnabled(context)) {
|
||||
hasReadReceipt = false
|
||||
|
@ -5072,7 +5078,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||
latestRevisionId,
|
||||
originalMessageId,
|
||||
editCount,
|
||||
isRead
|
||||
isRead,
|
||||
messageExtras
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ import org.thoughtcrime.securesms.database.model.MessageRecord
|
|||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.MessageExtras
|
||||
import org.thoughtcrime.securesms.database.model.serialize
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.groups.BadGroupIdException
|
||||
|
@ -97,6 +98,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
const val SNIPPET_URI = "snippet_uri"
|
||||
const val SNIPPET_CONTENT_TYPE = "snippet_content_type"
|
||||
const val SNIPPET_EXTRAS = "snippet_extras"
|
||||
const val SNIPPET_MESSAGE_EXTRAS = "snippet_message_extras"
|
||||
const val ARCHIVED = "archived"
|
||||
const val STATUS = "status"
|
||||
const val HAS_DELIVERY_RECEIPT = "has_delivery_receipt"
|
||||
|
@ -137,7 +139,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
$LAST_SCROLLED INTEGER DEFAULT 0,
|
||||
$PINNED INTEGER DEFAULT 0,
|
||||
$UNREAD_SELF_MENTION_COUNT INTEGER DEFAULT 0,
|
||||
$ACTIVE INTEGER DEFAULT 0
|
||||
$ACTIVE INTEGER DEFAULT 0,
|
||||
$SNIPPET_MESSAGE_EXTRAS BLOB DEFAULT NULL
|
||||
)
|
||||
"""
|
||||
|
||||
|
@ -164,6 +167,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
SNIPPET_URI,
|
||||
SNIPPET_CONTENT_TYPE,
|
||||
SNIPPET_EXTRAS,
|
||||
SNIPPET_MESSAGE_EXTRAS,
|
||||
ARCHIVED,
|
||||
STATUS,
|
||||
HAS_DELIVERY_RECEIPT,
|
||||
|
@ -223,7 +227,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
expiresIn: Long,
|
||||
readReceiptCount: Int,
|
||||
unreadCount: Int,
|
||||
unreadMentionCount: Int
|
||||
unreadMentionCount: Int,
|
||||
messageExtras: MessageExtras?
|
||||
) {
|
||||
var extraSerialized: String? = null
|
||||
|
||||
|
@ -249,7 +254,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
EXPIRES_IN to expiresIn,
|
||||
ACTIVE to 1,
|
||||
UNREAD_COUNT to unreadCount,
|
||||
UNREAD_SELF_MENTION_COUNT to unreadMentionCount
|
||||
UNREAD_SELF_MENTION_COUNT to unreadMentionCount,
|
||||
SNIPPET_MESSAGE_EXTRAS to messageExtras?.encode()
|
||||
)
|
||||
|
||||
writableDatabase
|
||||
|
@ -1479,7 +1485,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
expiresIn = 0,
|
||||
readReceiptCount = 0,
|
||||
unreadCount = 0,
|
||||
unreadMentionCount = 0
|
||||
unreadMentionCount = 0,
|
||||
messageExtras = null
|
||||
)
|
||||
}
|
||||
return@withinTransaction true
|
||||
|
@ -1508,7 +1515,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
expiresIn = record.expiresIn,
|
||||
readReceiptCount = record.hasReadReceipt().toInt(),
|
||||
unreadCount = unreadCount,
|
||||
unreadMentionCount = unreadMentionCount
|
||||
unreadMentionCount = unreadMentionCount,
|
||||
messageExtras = record.messageExtras
|
||||
)
|
||||
|
||||
if (notifyListeners) {
|
||||
|
@ -1667,6 +1675,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
SNIPPET_URI to null,
|
||||
SNIPPET_CONTENT_TYPE to null,
|
||||
SNIPPET_EXTRAS to null,
|
||||
SNIPPET_MESSAGE_EXTRAS to null,
|
||||
UNREAD_COUNT to 0,
|
||||
ARCHIVED to 0,
|
||||
STATUS to 0,
|
||||
|
@ -1898,6 +1907,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
|
||||
val hasReadReceipt = TextSecurePreferences.isReadReceiptsEnabled(context) && cursor.requireBoolean(HAS_READ_RECEIPT)
|
||||
val extraString = cursor.getString(cursor.getColumnIndexOrThrow(SNIPPET_EXTRAS))
|
||||
val messageExtras = cursor.getBlob(cursor.getColumnIndexOrThrow(SNIPPET_MESSAGE_EXTRAS))
|
||||
val extra: Extra? = if (extraString != null) {
|
||||
try {
|
||||
val jsonObject = SaneJSONObject(JSONObject(extraString))
|
||||
|
|
|
@ -74,6 +74,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V213_FixUsernameInE
|
|||
import org.thoughtcrime.securesms.database.helpers.migration.V214_PhoneNumberSharingColumn
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V215_RemoveAttachmentUniqueId
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V216_PhoneNumberDiscoverable
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V217_MessageTableExtrasColumn
|
||||
|
||||
/**
|
||||
* Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness.
|
||||
|
@ -150,10 +151,11 @@ object SignalDatabaseMigrations {
|
|||
213 to V213_FixUsernameInE164Column,
|
||||
214 to V214_PhoneNumberSharingColumn,
|
||||
215 to V215_RemoveAttachmentUniqueId,
|
||||
216 to V216_PhoneNumberDiscoverable
|
||||
216 to V216_PhoneNumberDiscoverable,
|
||||
217 to V217_MessageTableExtrasColumn
|
||||
)
|
||||
|
||||
const val DATABASE_VERSION = 216
|
||||
const val DATABASE_VERSION = 217
|
||||
|
||||
@JvmStatic
|
||||
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.database.helpers.migration
|
||||
|
||||
import android.app.Application
|
||||
import net.zetetic.database.sqlcipher.SQLiteDatabase
|
||||
|
||||
/**
|
||||
* Adds a message_extras column to the messages table. This allows us to
|
||||
* store extra data for messages in a more future proof and structured way.
|
||||
*/
|
||||
@Suppress("ClassName")
|
||||
object V217_MessageTableExtrasColumn : SignalDatabaseMigration {
|
||||
override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
db.execSQL("ALTER TABLE message ADD COLUMN message_extras BLOB DEFAULT NULL")
|
||||
db.execSQL("ALTER TABLE thread ADD COLUMN snippet_message_extras BLOB DEFAULT NULL")
|
||||
}
|
||||
}
|
|
@ -25,17 +25,53 @@ import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemov
|
|||
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember;
|
||||
import org.signal.storageservice.protos.groups.local.EnabledState;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GenericGroupUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupAdminStatusUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupAnnouncementOnlyChangeUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupAttributesAccessLevelChangeUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupAvatarUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupChangeChatUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupCreationUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupDescriptionUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInvitationAcceptedUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInvitationDeclinedUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInvitationRevokedUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInviteLinkAdminApprovalUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInviteLinkDisabledUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInviteLinkEnabledUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInviteLinkResetUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupJoinRequestApprovalUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupJoinRequestCanceledUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupJoinRequestUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMemberAddedUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMemberJoinedUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMemberLeftUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMemberRemovedUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMembershipAccessLevelChangeUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupNameUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupUnknownInviteeUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupV2AccessLevel;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupV2MigrationDroppedMembersUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupV2MigrationInvitedMembersUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupV2MigrationSelfInvitedUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupV2MigrationUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.SelfInvitedOtherUserToGroupUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.SelfInvitedToGroupUpdate;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GV2UpdateDescription;
|
||||
import org.thoughtcrime.securesms.groups.GV2AccessLevelUtil;
|
||||
import org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.util.ExpirationUtil;
|
||||
import org.thoughtcrime.securesms.util.SpanUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceIds;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -104,6 +140,485 @@ final class GroupsV2UpdateMessageProducer {
|
|||
}
|
||||
}
|
||||
|
||||
List<UpdateDescription> describeChanges(@NonNull List<GroupChangeChatUpdate.Update> groupUpdates) {
|
||||
List<UpdateDescription> updates = new LinkedList<>();
|
||||
for (GroupChangeChatUpdate.Update update : groupUpdates) {
|
||||
describeUpdate(update, updates);
|
||||
}
|
||||
|
||||
return updates;
|
||||
}
|
||||
|
||||
private void describeUpdate(@NonNull GroupChangeChatUpdate.Update update, @NonNull List<UpdateDescription> updates) {
|
||||
if (update.genericGroupUpdate != null) {
|
||||
describeGenericGroupUpdate(update.genericGroupUpdate, updates);
|
||||
} else if (update.groupCreationUpdate != null) {
|
||||
describeGroupCreationUpdate(update.groupCreationUpdate, updates);
|
||||
} else if (update.groupNameUpdate != null) {
|
||||
describeGroupNameUpdate(update.groupNameUpdate, updates);
|
||||
} else if (update.groupAvatarUpdate != null) {
|
||||
describeAvatarChange(update.groupAvatarUpdate, updates);
|
||||
} else if (update.groupDescriptionUpdate != null) {
|
||||
describeDescriptionChange(update.groupDescriptionUpdate, updates);
|
||||
} else if (update.groupMembershipAccessLevelChangeUpdate != null) {
|
||||
describeGroupMembershipAccessLevelChange(update.groupMembershipAccessLevelChangeUpdate, updates);
|
||||
} else if (update.groupAttributesAccessLevelChangeUpdate != null) {
|
||||
describeGroupAttributesAccessLevelChange(update.groupAttributesAccessLevelChangeUpdate, updates);
|
||||
} else if (update.groupAnnouncementOnlyChangeUpdate != null) {
|
||||
describeGroupAnnouncementOnlyUpdate(update.groupAnnouncementOnlyChangeUpdate, updates);
|
||||
} else if (update.groupAdminStatusUpdate != null) {
|
||||
describeAdminStatusChange(update.groupAdminStatusUpdate, updates);
|
||||
} else if (update.groupMemberLeftUpdate != null) {
|
||||
describeGroupMemberLeftChange(update.groupMemberLeftUpdate, updates);
|
||||
} else if (update.groupMemberRemovedUpdate != null) {
|
||||
describeGroupMemberRemovedChange(update.groupMemberRemovedUpdate, updates);
|
||||
} else if (update.selfInvitedToGroupUpdate != null) {
|
||||
describeSelfInvitedToGroupUpdate(update.selfInvitedToGroupUpdate, updates);
|
||||
} else if (update.selfInvitedOtherUserToGroupUpdate != null) {
|
||||
describeSelfInvitedOtherUserToGroupUpdate(update.selfInvitedOtherUserToGroupUpdate, updates);
|
||||
} else if (update.groupUnknownInviteeUpdate != null) {
|
||||
describeUnknownUsersInvitedUpdate(update.groupUnknownInviteeUpdate, updates);
|
||||
} else if (update.groupInvitationAcceptedUpdate != null) {
|
||||
describeGroupInvitationAcceptedUpdate(update.groupInvitationAcceptedUpdate, updates);
|
||||
} else if (update.groupMemberJoinedUpdate != null) {
|
||||
describeGroupMemberJoinedUpdate(update.groupMemberJoinedUpdate, updates);
|
||||
} else if (update.groupMemberAddedUpdate != null) {
|
||||
describeGroupMemberAddedUpdate(update.groupMemberAddedUpdate, updates);
|
||||
} else if (update.groupInvitationDeclinedUpdate != null) {
|
||||
describeGroupInvitationDeclinedUpdate(update.groupInvitationDeclinedUpdate, updates);
|
||||
} else if (update.groupInvitationRevokedUpdate != null) {
|
||||
describeGroupInvitationRevokedUpdate(update.groupInvitationRevokedUpdate, updates);
|
||||
} else if (update.groupJoinRequestUpdate != null) {
|
||||
describeGroupJoinRequestUpdate(update.groupJoinRequestUpdate, updates);
|
||||
} else if (update.groupJoinRequestApprovalUpdate != null) {
|
||||
describeGroupJoinRequestApprovedUpdate(update.groupJoinRequestApprovalUpdate, updates);
|
||||
} else if (update.groupJoinRequestCanceledUpdate != null) {
|
||||
describeGroupJoinRequestCanceledUpdate(update.groupJoinRequestCanceledUpdate, updates);
|
||||
} else if (update.groupInviteLinkResetUpdate != null) {
|
||||
describeInviteLinkResetUpdate(update.groupInviteLinkResetUpdate, updates);
|
||||
} else if (update.groupInviteLinkEnabledUpdate != null) {
|
||||
describeInviteLinkEnabledUpdate(update.groupInviteLinkEnabledUpdate, updates);
|
||||
} else if (update.groupInviteLinkDisabledUpdate != null) {
|
||||
describeInviteLinkDisabledUpdate(update.groupInviteLinkDisabledUpdate, updates);
|
||||
} else if (update.groupInviteLinkAdminApprovalUpdate != null) {
|
||||
describeGroupInviteLinkAdminApprovalUpdate(update.groupInviteLinkAdminApprovalUpdate, updates);
|
||||
} else if (update.groupV2MigrationUpdate != null) {
|
||||
describeGroupV2MigrationUpdate(update.groupV2MigrationUpdate, updates);
|
||||
} else if (update.groupV2MigrationDroppedMembersUpdate != null) {
|
||||
describeGroupV2MigrationDroppedMembersUpdate(update.groupV2MigrationDroppedMembersUpdate, updates);
|
||||
} else if (update.groupV2MigrationInvitedMembersUpdate != null) {
|
||||
describeGroupV2MigrationInvitedMembersUpdate(update.groupV2MigrationInvitedMembersUpdate, updates);
|
||||
} else if (update.groupV2MigrationSelfInvitedUpdate != null) {
|
||||
describeGroupV2MigrationSelfInvitedUpdate(update.groupV2MigrationSelfInvitedUpdate, updates);
|
||||
}
|
||||
}
|
||||
|
||||
private void describeGroupV2MigrationSelfInvitedUpdate(@NonNull GroupV2MigrationSelfInvitedUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_couldnt_be_added_to_the_new_group_and_have_been_invited_to_join), R.drawable.ic_update_group_add_16));
|
||||
}
|
||||
|
||||
private void describeGroupV2MigrationDroppedMembersUpdate(@NonNull GroupV2MigrationDroppedMembersUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
updates.add(updateDescription(context.getResources().getQuantityString(R.plurals.MessageRecord_members_couldnt_be_added_to_the_new_group_and_have_been_removed, update.droppedMembersCount, update.droppedMembersCount), R.drawable.ic_update_group_remove_16));
|
||||
}
|
||||
|
||||
private void describeGroupV2MigrationInvitedMembersUpdate(@NonNull GroupV2MigrationInvitedMembersUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
updates.add(updateDescription(context.getResources().getQuantityString(R.plurals.MessageRecord_members_couldnt_be_added_to_the_new_group_and_have_been_invited, update.invitedMembersCount, update.invitedMembersCount), R.drawable.ic_update_group_remove_16));
|
||||
}
|
||||
|
||||
private void describeGroupV2MigrationUpdate(@NonNull GroupV2MigrationUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_this_group_was_updated_to_a_new_group), R.drawable.ic_update_group_role_16));
|
||||
}
|
||||
|
||||
private void describeGroupInviteLinkAdminApprovalUpdate(@NonNull GroupInviteLinkAdminApprovalUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
if (update.updaterAci == null) {
|
||||
if (update.linkRequiresAdminApproval) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_admin_approval_for_the_group_link_has_been_turned_on), R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_admin_approval_for_the_group_link_has_been_turned_off), R.drawable.ic_update_group_role_16));
|
||||
}
|
||||
} else {
|
||||
if (selfIds.matches(update.updaterAci)) {
|
||||
if (update.linkRequiresAdminApproval) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_on_admin_approval_for_the_group_link), R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_off_admin_approval_for_the_group_link), R.drawable.ic_update_group_role_16));
|
||||
}
|
||||
} else {
|
||||
if (update.linkRequiresAdminApproval) {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_turned_on_admin_approval_for_the_group_link, update.updaterAci, R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_turned_off_admin_approval_for_the_group_link, update.updaterAci, R.drawable.ic_update_group_role_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void describeInviteLinkDisabledUpdate(@NonNull GroupInviteLinkDisabledUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
boolean editorIsYou = selfIds.matches(update.updaterAci);
|
||||
|
||||
if (update.updaterAci == null) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_link_has_been_turned_off), R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
if (editorIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_off_the_group_link), R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_turned_off_the_group_link, update.updaterAci, R.drawable.ic_update_group_role_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void describeInviteLinkEnabledUpdate(@NonNull GroupInviteLinkEnabledUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
boolean editorIsYou = selfIds.matches(update.updaterAci);
|
||||
|
||||
if (update.updaterAci == null) {
|
||||
if (update.linkRequiresAdminApproval) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_link_has_been_turned_on_with_admin_approval_on), R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_link_has_been_turned_on_with_admin_approval_off), R.drawable.ic_update_group_role_16));
|
||||
}
|
||||
} else {
|
||||
if (editorIsYou) {
|
||||
if (update.linkRequiresAdminApproval) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_on_the_group_link_with_admin_approval_on), R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_on_the_group_link_with_admin_approval_off), R.drawable.ic_update_group_role_16));
|
||||
}
|
||||
} else {
|
||||
if (update.linkRequiresAdminApproval) {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_turned_on_the_group_link_with_admin_approval_on, update.updaterAci, R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_turned_on_the_group_link_with_admin_approval_off, update.updaterAci, R.drawable.ic_update_group_role_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void describeInviteLinkResetUpdate(@NonNull GroupInviteLinkResetUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
if (update.updaterAci == null) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_link_has_been_reset), R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
if (selfIds.matches(update.updaterAci)) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_reset_the_group_link), R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_reset_the_group_link, update.updaterAci, R.drawable.ic_update_group_role_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void describeGroupJoinRequestCanceledUpdate(@NonNull GroupJoinRequestCanceledUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
boolean requestingMemberIsYou = selfIds.matches(update.requestorAci);
|
||||
|
||||
if (requestingMemberIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_canceled_your_request_to_join_the_group), R.drawable.ic_update_group_decline_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_canceled_their_request_to_join_the_group, update.requestorAci, R.drawable.ic_update_group_decline_16));
|
||||
}
|
||||
}
|
||||
|
||||
private void describeGroupJoinRequestApprovedUpdate(@NonNull GroupJoinRequestApprovalUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
boolean requestingMemberIsYou = selfIds.matches(update.requestorAci);
|
||||
|
||||
if (update.wasApproved) {
|
||||
if (update.updaterAci == null) {
|
||||
if (requestingMemberIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_your_request_to_join_the_group_has_been_approved), R.drawable.ic_update_group_accept_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_a_request_to_join_the_group_from_s_has_been_approved, update.requestorAci, R.drawable.ic_update_group_accept_16));
|
||||
}
|
||||
} else {
|
||||
if (requestingMemberIsYou) {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_approved_your_request_to_join_the_group, update.updaterAci, R.drawable.ic_update_group_accept_16));
|
||||
} else {
|
||||
boolean editorIsYou = selfIds.matches(update.updaterAci);
|
||||
|
||||
if (editorIsYou) {
|
||||
updates.add(updateDescription(R.string.MessageRecord_you_approved_a_request_to_join_the_group_from_s, update.requestorAci, R.drawable.ic_update_group_accept_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_approved_a_request_to_join_the_group_from_s, update.updaterAci, update.requestorAci, R.drawable.ic_update_group_accept_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (update.updaterAci == null) {
|
||||
if (requestingMemberIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_your_request_to_join_the_group_has_been_denied_by_an_admin), R.drawable.ic_update_group_decline_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_a_request_to_join_the_group_from_s_has_been_denied, update.requestorAci, R.drawable.ic_update_group_decline_16));
|
||||
}
|
||||
} else {
|
||||
if (requestingMemberIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_your_request_to_join_the_group_has_been_denied_by_an_admin), R.drawable.ic_update_group_decline_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_denied_a_request_to_join_the_group_from_s, update.updaterAci, update.requestorAci, R.drawable.ic_update_group_decline_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void describeGroupJoinRequestUpdate(@NonNull GroupJoinRequestUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
if (selfIds.matches(update.requestorAci)) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_sent_a_request_to_join_the_group), R.drawable.ic_update_group_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_requested_to_join_via_the_group_link, update.requestorAci, R.drawable.ic_update_group_16));
|
||||
}
|
||||
}
|
||||
|
||||
private void describeGroupInvitationRevokedUpdate(@NonNull GroupInvitationRevokedUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
int revokedMeCount = 0;
|
||||
for (GroupInvitationRevokedUpdate.Invitee invitee : update.invitees) {
|
||||
if (selfIds.matches(invitee.inviteeAci) || selfIds.matches(invitee.inviteePni)) {
|
||||
revokedMeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
int notMeInvitees = update.invitees.size() - revokedMeCount;
|
||||
|
||||
if (update.updaterAci == null) {
|
||||
if (revokedMeCount > 0) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_an_admin_revoked_your_invitation_to_the_group), R.drawable.ic_update_group_decline_16));
|
||||
}
|
||||
if (notMeInvitees > 0) {
|
||||
updates.add(updateDescription(context.getResources().getQuantityString(R.plurals.MessageRecord_d_invitations_were_revoked, notMeInvitees, notMeInvitees), R.drawable.ic_update_group_decline_16));
|
||||
}
|
||||
} else {
|
||||
if (revokedMeCount > 0) {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_revoked_your_invitation_to_the_group, update.updaterAci, R.drawable.ic_update_group_decline_16));
|
||||
}
|
||||
if (selfIds.matches(update.updaterAci)) {
|
||||
updates.add(updateDescription(context.getResources().getQuantityString(R.plurals.MessageRecord_you_revoked_invites, notMeInvitees, notMeInvitees), R.drawable.ic_update_group_decline_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.plurals.MessageRecord_s_revoked_invites, notMeInvitees, update.updaterAci, notMeInvitees, R.drawable.ic_update_group_decline_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void describeGroupInvitationDeclinedUpdate(@NonNull GroupInvitationDeclinedUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
if (selfIds.matches(update.inviteeAci)) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_declined_the_invitation_to_the_group), R.drawable.ic_update_group_decline_16));
|
||||
} else {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_someone_declined_an_invitation_to_the_group), R.drawable.ic_update_group_decline_16));
|
||||
}
|
||||
}
|
||||
|
||||
private void describeGroupMemberAddedUpdate(@NonNull GroupMemberAddedUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
boolean newMemberIsYou = selfIds.matches(update.newMemberAci);
|
||||
|
||||
if (update.updaterAci == null) {
|
||||
if (newMemberIsYou) {
|
||||
updates.add(0, updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_joined_the_group, update.newMemberAci, R.drawable.ic_update_group_add_16));
|
||||
}
|
||||
} else if (update.hadOpenInvitation) {
|
||||
if (selfIds.matches(update.updaterAci)) {
|
||||
updates.add(updateDescription(R.string.MessageRecord_you_added_invited_member_s, update.newMemberAci, R.drawable.ic_update_group_add_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_added_invited_member_s, update.updaterAci, update.newMemberAci, R.drawable.ic_update_group_add_16));
|
||||
}
|
||||
} else {
|
||||
if (newMemberIsYou) {
|
||||
updates.add(0, updateDescription(R.string.MessageRecord_s_added_you, update.updaterAci, R.drawable.ic_update_group_add_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_added_s, update.updaterAci, update.newMemberAci, R.drawable.ic_update_group_add_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void describeGroupMemberJoinedUpdate(@NonNull GroupMemberJoinedUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
boolean newMemberIsYou = selfIds.matches(update.newMemberAci);
|
||||
|
||||
if (newMemberIsYou) {
|
||||
updates.add(0, updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_joined_the_group, update.newMemberAci, R.drawable.ic_update_group_add_16));
|
||||
}
|
||||
}
|
||||
|
||||
private void describeGroupInvitationAcceptedUpdate(@NonNull GroupInvitationAcceptedUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
if (selfIds.matches(update.newMemberAci)) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_accepted_invite), R.drawable.ic_update_group_accept_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_accepted_invite, update.newMemberAci, R.drawable.ic_update_group_accept_16));
|
||||
}
|
||||
}
|
||||
|
||||
private void describeUnknownUsersInvitedUpdate(@NonNull GroupUnknownInviteeUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
if (update.inviterAci == null) {
|
||||
updates.add(updateDescription(context.getResources().getQuantityString(R.plurals.MessageRecord_d_people_were_invited_to_the_group, update.inviteeCount, update.inviteeCount), R.drawable.ic_update_group_add_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.plurals.MessageRecord_s_invited_members, update.inviteeCount, update.inviterAci, update.inviteeCount, R.drawable.ic_update_group_add_16));
|
||||
}
|
||||
}
|
||||
private void describeSelfInvitedOtherUserToGroupUpdate(@NonNull SelfInvitedOtherUserToGroupUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
updates.add(updateDescription(R.string.MessageRecord_you_invited_s_to_the_group, update.inviteeServiceId, R.drawable.ic_update_group_add_16));
|
||||
}
|
||||
|
||||
private void describeSelfInvitedToGroupUpdate(@NonNull SelfInvitedToGroupUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
if (update.inviterAci == null) {
|
||||
updates.add(0, updateDescription(context.getString(R.string.MessageRecord_you_were_invited_to_the_group), R.drawable.ic_update_group_add_16));
|
||||
} else {
|
||||
updates.add(0, updateDescription(R.string.MessageRecord_s_invited_you_to_the_group, update.inviterAci, R.drawable.ic_update_group_add_16));
|
||||
}
|
||||
}
|
||||
|
||||
private void describeGenericGroupUpdate(@NonNull GenericGroupUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
if (update.updaterAci == null) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_was_updated), R.drawable.ic_update_group_16));
|
||||
} else {
|
||||
boolean editorIsYou = selfIds.matches(update.updaterAci);
|
||||
|
||||
if (editorIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_updated_group), R.drawable.ic_update_group_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_updated_group, update.updaterAci, R.drawable.ic_update_group_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void describeGroupCreationUpdate(@NonNull GroupCreationUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
if (update.updaterAci == null) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_group_updated), R.drawable.ic_update_group_16));
|
||||
} else {
|
||||
if (selfIds.matches(update.updaterAci)) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_created_the_group), R.drawable.ic_update_group_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_added_you, update.updaterAci, R.drawable.ic_update_group_add_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void describeGroupNameUpdate(@NonNull GroupNameUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
if (update.updaterAci == null) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_name_has_changed_to_s, StringUtil.isolateBidi(update.newGroupName)), R.drawable.ic_update_group_name_16));
|
||||
} else {
|
||||
String newTitle = StringUtil.isolateBidi(update.newGroupName);
|
||||
if (selfIds.matches(update.updaterAci)) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_the_group_name_to_s, newTitle), R.drawable.ic_update_group_name_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_changed_the_group_name_to_s, update.updaterAci, newTitle, R.drawable.ic_update_group_name_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void describeGroupMembershipAccessLevelChange(@NonNull GroupMembershipAccessLevelChangeUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
if (update.accessLevel == GroupV2AccessLevel.UNKNOWN) {
|
||||
return;
|
||||
}
|
||||
String accessLevel = GV2AccessLevelUtil.toString(context, backupGv2AccessLevelToGroups(update.accessLevel));
|
||||
if (update.updaterAci == null) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_who_can_edit_group_membership_has_been_changed_to_s, accessLevel), R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
boolean editorIsYou = selfIds.matches(update.updaterAci);
|
||||
|
||||
if (editorIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_who_can_edit_group_membership_to_s, accessLevel), R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_changed_who_can_edit_group_membership_to_s, update.updaterAci, accessLevel, R.drawable.ic_update_group_role_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void describeGroupAttributesAccessLevelChange(@NonNull GroupAttributesAccessLevelChangeUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
if (update.accessLevel == GroupV2AccessLevel.UNKNOWN) {
|
||||
return;
|
||||
}
|
||||
String accessLevel = GV2AccessLevelUtil.toString(context, backupGv2AccessLevelToGroups(update.accessLevel));
|
||||
if (update.updaterAci == null) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_who_can_edit_group_info_has_been_changed_to_s, accessLevel), R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
boolean editorIsYou = selfIds.matches(update.updaterAci);
|
||||
|
||||
if (editorIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_who_can_edit_group_info_to_s, accessLevel), R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_changed_who_can_edit_group_info_to_s, update.updaterAci, accessLevel, R.drawable.ic_update_group_role_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void describeGroupAnnouncementOnlyUpdate(@NonNull GroupAnnouncementOnlyChangeUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
if (update.updaterAci == null) {
|
||||
if (update.isAnnouncementOnly) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_allow_only_admins_to_send), R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_allow_all_members_to_send), R.drawable.ic_update_group_role_16));
|
||||
}
|
||||
} else {
|
||||
boolean editorIsYou = selfIds.matches(update.updaterAci);
|
||||
|
||||
if (update.isAnnouncementOnly) {
|
||||
if (editorIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_allow_only_admins_to_send), R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_allow_only_admins_to_send, update.updaterAci, R.drawable.ic_update_group_role_16));
|
||||
}
|
||||
} else {
|
||||
if (editorIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_allow_all_members_to_send), R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_allow_all_members_to_send, update.updaterAci, R.drawable.ic_update_group_role_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void describeGroupMemberLeftChange(@NonNull GroupMemberLeftUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
if (update.aci == null) {
|
||||
return;
|
||||
}
|
||||
boolean editorIsYou = selfIds.matches(update.aci);
|
||||
if (editorIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_left_the_group), R.drawable.ic_update_group_leave_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_left_the_group, update.aci, R.drawable.ic_update_group_leave_16));
|
||||
}
|
||||
}
|
||||
|
||||
private void describeGroupMemberRemovedChange(@NonNull GroupMemberRemovedUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||
if (update.removerAci == null) {
|
||||
boolean removedMemberIsYou = selfIds.matches(update.removedAci);
|
||||
|
||||
if (removedMemberIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_are_no_longer_in_the_group), R.drawable.ic_update_group_leave_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_is_no_longer_in_the_group, update.removedAci, R.drawable.ic_update_group_leave_16));
|
||||
}
|
||||
} else {
|
||||
boolean editorIsYou = selfIds.matches(update.removerAci);
|
||||
|
||||
boolean removedMemberIsYou = selfIds.matches(update.removedAci);
|
||||
|
||||
if (editorIsYou) {
|
||||
if (removedMemberIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_left_the_group), R.drawable.ic_update_group_leave_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_you_removed_s, update.removedAci, R.drawable.ic_update_group_remove_16));
|
||||
}
|
||||
} else {
|
||||
if (removedMemberIsYou) {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_removed_you_from_the_group, update.removerAci, R.drawable.ic_update_group_remove_16));
|
||||
} else {
|
||||
if (update.removerAci.equals(update.removedAci)) {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_left_the_group, update.removedAci, R.drawable.ic_update_group_leave_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_removed_s, update.removerAci, update.removedAci, R.drawable.ic_update_group_remove_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private AccessControl.AccessRequired backupGv2AccessLevelToGroups(@NonNull GroupV2AccessLevel accessLevel) {
|
||||
switch (accessLevel) {
|
||||
case ANY: return AccessControl.AccessRequired.ANY;
|
||||
case MEMBER: return AccessControl.AccessRequired.MEMBER;
|
||||
case ADMINISTRATOR: return AccessControl.AccessRequired.ADMINISTRATOR;
|
||||
case UNSATISFIABLE: return AccessControl.AccessRequired.UNSATISFIABLE;
|
||||
default:
|
||||
case UNKNOWN: return AccessControl.AccessRequired.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
List<UpdateDescription> describeChanges(@Nullable DecryptedGroup previousGroupState, @NonNull DecryptedGroupChange change) {
|
||||
if (new DecryptedGroup().equals(previousGroupState)) {
|
||||
previousGroupState = null;
|
||||
|
@ -317,6 +832,51 @@ final class GroupsV2UpdateMessageProducer {
|
|||
}
|
||||
}
|
||||
|
||||
private void describeAdminStatusChange(@NonNull GroupAdminStatusUpdate groupAdminStatusUpdate, List<UpdateDescription> updates) {
|
||||
boolean changedMemberIsYou = selfIds.matches(groupAdminStatusUpdate.memberAci);
|
||||
|
||||
if (groupAdminStatusUpdate.updaterAci != null) {
|
||||
boolean editorIsYou = selfIds.matches(groupAdminStatusUpdate.updaterAci);
|
||||
|
||||
if (groupAdminStatusUpdate.wasAdminStatusGranted) {
|
||||
if (editorIsYou) {
|
||||
updates.add(updateDescription(R.string.MessageRecord_you_made_s_an_admin, groupAdminStatusUpdate.memberAci, R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
if (changedMemberIsYou) {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_made_you_an_admin, groupAdminStatusUpdate.updaterAci, R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_made_s_an_admin, groupAdminStatusUpdate.updaterAci, groupAdminStatusUpdate.memberAci, R.drawable.ic_update_group_role_16));
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (editorIsYou) {
|
||||
updates.add(updateDescription(R.string.MessageRecord_you_revoked_admin_privileges_from_s, groupAdminStatusUpdate.memberAci, R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
if (changedMemberIsYou) {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_revoked_your_admin_privileges, groupAdminStatusUpdate.updaterAci, R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_revoked_admin_privileges_from_s, groupAdminStatusUpdate.updaterAci, groupAdminStatusUpdate.memberAci, R.drawable.ic_update_group_role_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (groupAdminStatusUpdate.wasAdminStatusGranted) {
|
||||
if (changedMemberIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_are_now_an_admin), R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_is_now_an_admin, groupAdminStatusUpdate.memberAci, R.drawable.ic_update_group_role_16));
|
||||
}
|
||||
} else {
|
||||
if (changedMemberIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_are_no_longer_an_admin), R.drawable.ic_update_group_role_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_is_no_longer_an_admin, groupAdminStatusUpdate.memberAci, R.drawable.ic_update_group_role_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void describeInvitations(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
|
||||
boolean editorIsYou = selfIds.matches(change.editorServiceIdBytes);
|
||||
int notYouInviteCount = 0;
|
||||
|
@ -481,6 +1041,20 @@ final class GroupsV2UpdateMessageProducer {
|
|||
}
|
||||
}
|
||||
|
||||
private void describeDescriptionChange(@NonNull GroupDescriptionUpdate groupDescriptionUpdate, @NonNull List<UpdateDescription> updates) {
|
||||
if (groupDescriptionUpdate.updaterAci != null) {
|
||||
boolean editorIsYou = selfIds.matches(groupDescriptionUpdate.updaterAci);
|
||||
|
||||
if (editorIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_the_group_description), R.drawable.ic_update_group_name_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_changed_the_group_description, groupDescriptionUpdate.updaterAci, R.drawable.ic_update_group_name_16));
|
||||
}
|
||||
} else {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_name_has_changed_to_s, StringUtil.isolateBidi(groupDescriptionUpdate.newDescription)), R.drawable.ic_update_group_name_16));
|
||||
}
|
||||
}
|
||||
|
||||
private void describeUnknownEditorNewDescription(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
|
||||
if (change.newDescription != null) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_description_has_changed), R.drawable.ic_update_group_name_16));
|
||||
|
@ -499,6 +1073,20 @@ final class GroupsV2UpdateMessageProducer {
|
|||
}
|
||||
}
|
||||
|
||||
private void describeAvatarChange(@NonNull GroupAvatarUpdate groupAvatarUpdate, @NonNull List<UpdateDescription> updates) {
|
||||
if (groupAvatarUpdate.updaterAci != null) {
|
||||
boolean editorIsYou = selfIds.matches(groupAvatarUpdate.updaterAci);
|
||||
|
||||
if (editorIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_the_group_avatar), R.drawable.ic_update_group_avatar_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_changed_the_group_avatar, groupAvatarUpdate.updaterAci, R.drawable.ic_update_group_avatar_16));
|
||||
}
|
||||
} else {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_group_avatar_has_been_changed), R.drawable.ic_update_group_avatar_16));
|
||||
}
|
||||
}
|
||||
|
||||
private void describeUnknownEditorNewAvatar(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
|
||||
if (change.newAvatar != null) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_group_avatar_has_been_changed), R.drawable.ic_update_group_avatar_16));
|
||||
|
|
|
@ -56,7 +56,8 @@ public class InMemoryMessageRecord extends MessageRecord {
|
|||
false,
|
||||
-1,
|
||||
null,
|
||||
0);
|
||||
0,
|
||||
null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
|||
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GroupCallUpdateDetails;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.MessageExtras;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ProfileChangeDetails;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.SessionSwitchoverEvent;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ThreadMergeEvent;
|
||||
|
@ -104,6 +105,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
private final long receiptTimestamp;
|
||||
private final MessageId originalMessageId;
|
||||
private final int revisionNumber;
|
||||
private final MessageExtras messageExtras;
|
||||
|
||||
protected Boolean isJumboji = null;
|
||||
|
||||
|
@ -123,7 +125,8 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
boolean viewed,
|
||||
long receiptTimestamp,
|
||||
@Nullable MessageId originalMessageId,
|
||||
int revisionNumber)
|
||||
int revisionNumber,
|
||||
@Nullable MessageExtras messageExtras)
|
||||
{
|
||||
super(body, fromRecipient, toRecipient, dateSent, dateReceived,
|
||||
threadId, deliveryStatus, hasDeliveryReceipt, type,
|
||||
|
@ -143,6 +146,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
this.receiptTimestamp = receiptTimestamp;
|
||||
this.originalMessageId = originalMessageId;
|
||||
this.revisionNumber = revisionNumber;
|
||||
this.messageExtras = messageExtras;
|
||||
}
|
||||
|
||||
public abstract boolean isMms();
|
||||
|
@ -287,6 +291,10 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
return selfCreatedGroup(change);
|
||||
}
|
||||
|
||||
@Nullable public MessageExtras getMessageExtras() {
|
||||
return messageExtras;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@Nullable DecryptedGroupV2Context getDecryptedGroupV2Context() {
|
||||
if (!isGroupUpdate() || !isGroupV2()) {
|
||||
|
@ -315,6 +323,30 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
try {
|
||||
byte[] decoded = Base64.decode(body);
|
||||
DecryptedGroupV2Context decryptedGroupV2Context = DecryptedGroupV2Context.ADAPTER.decode(decoded);
|
||||
return getGv2ChangeDescription(context, decryptedGroupV2Context, recipientClickHandler);
|
||||
} catch (IOException | IllegalArgumentException | IllegalStateException e) {
|
||||
Log.w(TAG, "GV2 Message update detail could not be read", e);
|
||||
return staticUpdateDescription(context.getString(R.string.MessageRecord_group_updated), R.drawable.ic_update_group_16);
|
||||
}
|
||||
}
|
||||
|
||||
public static @NonNull UpdateDescription getGv2ChangeDescription(@NonNull Context context, @NonNull MessageExtras messageExtras, @Nullable Consumer<RecipientId> recipientClickHandler) {
|
||||
if (messageExtras.gv2UpdateDescription != null) {
|
||||
if (messageExtras.gv2UpdateDescription.groupChangeUpdate != null) {
|
||||
GroupsV2UpdateMessageProducer updateMessageProducer = new GroupsV2UpdateMessageProducer(context, SignalStore.account().getServiceIds(), recipientClickHandler);
|
||||
|
||||
return UpdateDescription.concatWithNewLines(updateMessageProducer.describeChanges(messageExtras.gv2UpdateDescription.groupChangeUpdate.updates));
|
||||
} else if (messageExtras.gv2UpdateDescription.gv2ChangeDescription != null) {
|
||||
return getGv2ChangeDescription(context, messageExtras.gv2UpdateDescription.gv2ChangeDescription, recipientClickHandler);
|
||||
} else {
|
||||
Log.w(TAG, "GV2 Update Description missing group change update!");
|
||||
}
|
||||
}
|
||||
return staticUpdateDescription(context.getString(R.string.MessageRecord_group_updated), R.drawable.ic_update_group_16);
|
||||
}
|
||||
|
||||
public static @NonNull UpdateDescription getGv2ChangeDescription(@NonNull Context context, @NonNull DecryptedGroupV2Context decryptedGroupV2Context, @Nullable Consumer<RecipientId> recipientClickHandler) {
|
||||
try {
|
||||
GroupsV2UpdateMessageProducer updateMessageProducer = new GroupsV2UpdateMessageProducer(context, SignalStore.account().getServiceIds(), recipientClickHandler);
|
||||
|
||||
if (decryptedGroupV2Context.change != null && ((decryptedGroupV2Context.groupState != null && decryptedGroupV2Context.groupState.revision != 0) || decryptedGroupV2Context.previousGroupState != null)) {
|
||||
|
@ -332,7 +364,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
}
|
||||
return UpdateDescription.concatWithNewLines(newGroupDescriptions);
|
||||
}
|
||||
} catch (IOException | IllegalArgumentException | IllegalStateException e) {
|
||||
} catch (IllegalArgumentException | IllegalStateException e) {
|
||||
Log.w(TAG, "GV2 Message update detail could not be read", e);
|
||||
return staticUpdateDescription(context.getString(R.string.MessageRecord_group_updated), R.drawable.ic_update_group_16);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
|||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.MessageExtras;
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
|
@ -111,12 +112,13 @@ public class MmsMessageRecord extends MessageRecord {
|
|||
@Nullable MessageId latestRevisionId,
|
||||
@Nullable MessageId originalMessageId,
|
||||
int revisionNumber,
|
||||
boolean isRead)
|
||||
boolean isRead,
|
||||
@Nullable MessageExtras messageExtras)
|
||||
{
|
||||
super(id, body, fromRecipient, fromDeviceId, toRecipient,
|
||||
dateSent, dateReceived, dateServer, threadId, Status.STATUS_NONE, hasDeliveryReceipt,
|
||||
mailbox, mismatches, failures, subscriptionId, expiresIn, expireStarted, hasReadReceipt,
|
||||
unidentified, reactions, remoteDelete, notifiedTimestamp, viewed, receiptTimestamp, originalMessageId, revisionNumber);
|
||||
unidentified, reactions, remoteDelete, notifiedTimestamp, viewed, receiptTimestamp, originalMessageId, revisionNumber, messageExtras);
|
||||
|
||||
this.slideDeck = slideDeck;
|
||||
this.quote = quote;
|
||||
|
@ -299,7 +301,7 @@ public class MmsMessageRecord extends MessageRecord {
|
|||
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
|
||||
hasReadReceipt(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), reactions, isRemoteDelete(), mentionsSelf,
|
||||
getNotifiedTimestamp(), isViewed(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getScheduledDate(), getLatestRevisionId(),
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead());
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead(), getMessageExtras());
|
||||
}
|
||||
|
||||
public @NonNull MmsMessageRecord withoutQuote() {
|
||||
|
@ -307,7 +309,7 @@ public class MmsMessageRecord extends MessageRecord {
|
|||
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
|
||||
hasReadReceipt(), null, getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
|
||||
getNotifiedTimestamp(), isViewed(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getScheduledDate(), getLatestRevisionId(),
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead());
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead(), getMessageExtras());
|
||||
}
|
||||
|
||||
public @NonNull MmsMessageRecord withAttachments(@NonNull List<DatabaseAttachment> attachments) {
|
||||
|
@ -329,7 +331,7 @@ public class MmsMessageRecord extends MessageRecord {
|
|||
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
|
||||
hasReadReceipt(), quote, contacts, linkPreviews, isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
|
||||
getNotifiedTimestamp(), isViewed(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getScheduledDate(), getLatestRevisionId(),
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead());
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead(), getMessageExtras());
|
||||
}
|
||||
|
||||
public @NonNull MmsMessageRecord withPayment(@NonNull Payment payment) {
|
||||
|
@ -337,7 +339,7 @@ public class MmsMessageRecord extends MessageRecord {
|
|||
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
|
||||
hasReadReceipt(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
|
||||
getNotifiedTimestamp(), isViewed(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), payment, getCall(), getScheduledDate(), getLatestRevisionId(),
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead());
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead(), getMessageExtras());
|
||||
}
|
||||
|
||||
|
||||
|
@ -346,7 +348,7 @@ public class MmsMessageRecord extends MessageRecord {
|
|||
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
|
||||
hasReadReceipt(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
|
||||
getNotifiedTimestamp(), isViewed(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), call, getScheduledDate(), getLatestRevisionId(),
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead());
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead(), getMessageExtras());
|
||||
}
|
||||
|
||||
private static @NonNull List<Contact> updateContacts(@NonNull List<Contact> contacts, @NonNull Map<AttachmentId, DatabaseAttachment> attachmentIdMap) {
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.database.MessageTypes;
|
|||
import org.thoughtcrime.securesms.database.ThreadTable;
|
||||
import org.thoughtcrime.securesms.database.ThreadTable.Extra;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.MessageExtras;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.whispersystems.signalservice.api.util.Preconditions;
|
||||
|
@ -57,6 +58,7 @@ public final class ThreadRecord {
|
|||
private final long lastSeen;
|
||||
private final boolean isPinned;
|
||||
private final int unreadSelfMentionsCount;
|
||||
private final MessageExtras messageExtras;
|
||||
|
||||
private ThreadRecord(@NonNull Builder builder) {
|
||||
this.threadId = builder.threadId;
|
||||
|
@ -79,6 +81,7 @@ public final class ThreadRecord {
|
|||
this.lastSeen = builder.lastSeen;
|
||||
this.isPinned = builder.isPinned;
|
||||
this.unreadSelfMentionsCount = builder.unreadSelfMentionsCount;
|
||||
this.messageExtras = builder.messageExtras;
|
||||
}
|
||||
|
||||
public long getThreadId() {
|
||||
|
@ -189,6 +192,10 @@ public final class ThreadRecord {
|
|||
return extra != null && extra.isScheduled();
|
||||
}
|
||||
|
||||
public @Nullable MessageExtras getMessageExtras() {
|
||||
return messageExtras;
|
||||
}
|
||||
|
||||
public @Nullable RecipientId getGroupAddedBy() {
|
||||
if (extra != null && extra.getGroupAddedBy() != null) return RecipientId.from(extra.getGroupAddedBy());
|
||||
else return null;
|
||||
|
@ -307,6 +314,7 @@ public final class ThreadRecord {
|
|||
private long lastSeen;
|
||||
private boolean isPinned;
|
||||
private int unreadSelfMentionsCount;
|
||||
private MessageExtras messageExtras;
|
||||
|
||||
public Builder(long threadId) {
|
||||
this.threadId = threadId;
|
||||
|
@ -407,6 +415,11 @@ public final class ThreadRecord {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder setSnippetMessageExtras(@Nullable MessageExtras messageExtras) {
|
||||
this.messageExtras = messageExtras;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setUnreadSelfMentionsCount(int unreadSelfMentionsCount) {
|
||||
this.unreadSelfMentionsCount = unreadSelfMentionsCount;
|
||||
return this;
|
||||
|
|
|
@ -7,7 +7,6 @@ option java_package = "org.thoughtcrime.securesms.backup.v2.proto";
|
|||
message BackupInfo {
|
||||
uint64 version = 1;
|
||||
uint64 backupTimeMs = 2;
|
||||
bytes iv = 3;
|
||||
}
|
||||
|
||||
message Frame {
|
||||
|
@ -207,6 +206,9 @@ message ChatItem {
|
|||
repeated SendStatus sendStatus = 1;
|
||||
}
|
||||
|
||||
message DirectionlessMessageDetails {
|
||||
}
|
||||
|
||||
uint64 chatId = 1; // conversation id
|
||||
uint64 authorId = 2; // recipient id
|
||||
uint64 dateSent = 3;
|
||||
|
@ -217,8 +219,9 @@ message ChatItem {
|
|||
bool sms = 8;
|
||||
|
||||
oneof directionalDetails {
|
||||
IncomingMessageDetails incoming = 10;
|
||||
OutgoingMessageDetails outgoing = 12;
|
||||
IncomingMessageDetails incoming = 9;
|
||||
OutgoingMessageDetails outgoing = 10;
|
||||
DirectionlessMessageDetails directionless = 11;
|
||||
}
|
||||
|
||||
oneof item {
|
||||
|
@ -415,16 +418,17 @@ message FilePointer {
|
|||
|
||||
optional bytes key = 5;
|
||||
optional string contentType = 6;
|
||||
// Size of fullsize decrypted media blob in bytes.
|
||||
// Can be ignored if unset/unavailable.
|
||||
optional uint32 size = 7;
|
||||
optional bytes digest = 8;
|
||||
optional bytes incrementalMac = 9;
|
||||
optional bytes incrementalMacChunkSize = 10;
|
||||
optional string fileName = 11;
|
||||
optional uint32 flags = 12;
|
||||
optional uint32 width = 13;
|
||||
optional uint32 height = 14;
|
||||
optional string caption = 15;
|
||||
optional string blurHash = 16;
|
||||
optional bytes incrementalMac = 8;
|
||||
optional bytes incrementalMacChunkSize = 9;
|
||||
optional string fileName = 10;
|
||||
optional uint32 flags = 11;
|
||||
optional uint32 width = 12;
|
||||
optional uint32 height = 13;
|
||||
optional string caption = 14;
|
||||
optional string blurHash = 15;
|
||||
}
|
||||
|
||||
message Quote {
|
||||
|
@ -478,7 +482,7 @@ message Reaction {
|
|||
message ChatUpdateMessage {
|
||||
oneof update {
|
||||
SimpleChatUpdate simpleUpdate = 1;
|
||||
GroupDescriptionChatUpdate groupDescription = 2;
|
||||
GroupChangeChatUpdate groupChange = 2;
|
||||
ExpirationTimerChatUpdate expirationTimerChange = 3;
|
||||
ProfileChangeChatUpdate profileChange = 4;
|
||||
ThreadMergeChatUpdate threadMerge = 5;
|
||||
|
@ -533,10 +537,6 @@ message SimpleChatUpdate {
|
|||
Type type = 1;
|
||||
}
|
||||
|
||||
message GroupDescriptionChatUpdate {
|
||||
string newDescription = 1;
|
||||
}
|
||||
|
||||
message ExpirationTimerChatUpdate {
|
||||
uint32 expiresInMs = 1;
|
||||
}
|
||||
|
@ -554,6 +554,246 @@ message SessionSwitchoverChatUpdate {
|
|||
uint64 e164 = 1;
|
||||
}
|
||||
|
||||
message GroupChangeChatUpdate {
|
||||
message Update {
|
||||
// Note: group expiration timer changes are represented as ExpirationTimerChatUpdate.
|
||||
oneof update {
|
||||
GenericGroupUpdate genericGroupUpdate = 1;
|
||||
GroupCreationUpdate groupCreationUpdate = 2;
|
||||
GroupNameUpdate groupNameUpdate = 3;
|
||||
GroupAvatarUpdate groupAvatarUpdate = 4;
|
||||
GroupDescriptionUpdate groupDescriptionUpdate = 5;
|
||||
GroupMembershipAccessLevelChangeUpdate groupMembershipAccessLevelChangeUpdate = 6;
|
||||
GroupAttributesAccessLevelChangeUpdate groupAttributesAccessLevelChangeUpdate = 7;
|
||||
GroupAnnouncementOnlyChangeUpdate groupAnnouncementOnlyChangeUpdate = 8;
|
||||
GroupAdminStatusUpdate groupAdminStatusUpdate = 9;
|
||||
GroupMemberLeftUpdate groupMemberLeftUpdate = 10;
|
||||
GroupMemberRemovedUpdate groupMemberRemovedUpdate = 11;
|
||||
SelfInvitedToGroupUpdate selfInvitedToGroupUpdate = 12;
|
||||
SelfInvitedOtherUserToGroupUpdate selfInvitedOtherUserToGroupUpdate = 13;
|
||||
GroupUnknownInviteeUpdate groupUnknownInviteeUpdate = 14;
|
||||
GroupInvitationAcceptedUpdate groupInvitationAcceptedUpdate = 15;
|
||||
GroupInvitationDeclinedUpdate groupInvitationDeclinedUpdate = 16;
|
||||
GroupMemberJoinedUpdate groupMemberJoinedUpdate = 17;
|
||||
GroupMemberAddedUpdate groupMemberAddedUpdate = 18;
|
||||
GroupSelfInvitationRevokedUpdate groupSelfInvitationRevokedUpdate = 19;
|
||||
GroupInvitationRevokedUpdate groupInvitationRevokedUpdate = 20;
|
||||
GroupJoinRequestUpdate groupJoinRequestUpdate = 21;
|
||||
GroupJoinRequestApprovalUpdate groupJoinRequestApprovalUpdate = 22;
|
||||
GroupJoinRequestCanceledUpdate groupJoinRequestCanceledUpdate = 23;
|
||||
GroupInviteLinkResetUpdate groupInviteLinkResetUpdate = 24;
|
||||
GroupInviteLinkEnabledUpdate groupInviteLinkEnabledUpdate = 25;
|
||||
GroupInviteLinkAdminApprovalUpdate groupInviteLinkAdminApprovalUpdate = 26;
|
||||
GroupInviteLinkDisabledUpdate groupInviteLinkDisabledUpdate = 27;
|
||||
GroupMemberJoinedByLinkUpdate groupMemberJoinedByLinkUpdate = 28;
|
||||
GroupV2MigrationUpdate groupV2MigrationUpdate = 29;
|
||||
GroupV2MigrationSelfInvitedUpdate groupV2MigrationSelfInvitedUpdate = 30;
|
||||
GroupV2MigrationInvitedMembersUpdate groupV2MigrationInvitedMembersUpdate = 31;
|
||||
GroupV2MigrationDroppedMembersUpdate groupV2MigrationDroppedMembersUpdate = 32;
|
||||
GroupSequenceOfRequestsAndCancelsUpdate groupSequenceOfRequestsAndCancelsUpdate = 33;
|
||||
}
|
||||
}
|
||||
|
||||
// Must be one or more; all updates batched together came from
|
||||
// a single batched group state update.
|
||||
repeated Update updates = 1;
|
||||
}
|
||||
|
||||
message GenericGroupUpdate {
|
||||
optional bytes updaterAci = 1;
|
||||
}
|
||||
|
||||
message GroupCreationUpdate {
|
||||
optional bytes updaterAci = 1;
|
||||
}
|
||||
|
||||
message GroupNameUpdate {
|
||||
optional bytes updaterAci = 1;
|
||||
// Null value means the group name was removed.
|
||||
optional string newGroupName = 2;
|
||||
}
|
||||
|
||||
message GroupAvatarUpdate {
|
||||
optional bytes updaterAci = 1;
|
||||
bool wasRemoved = 2;
|
||||
}
|
||||
|
||||
message GroupDescriptionUpdate {
|
||||
optional bytes updaterAci = 1;
|
||||
// Null value means the group description was removed.
|
||||
optional string newDescription = 2;
|
||||
}
|
||||
|
||||
enum GroupV2AccessLevel {
|
||||
UNKNOWN = 0;
|
||||
ANY = 1;
|
||||
MEMBER = 2;
|
||||
ADMINISTRATOR = 3;
|
||||
UNSATISFIABLE = 4;
|
||||
}
|
||||
|
||||
message GroupMembershipAccessLevelChangeUpdate {
|
||||
optional bytes updaterAci = 1;
|
||||
GroupV2AccessLevel accessLevel = 2;
|
||||
}
|
||||
|
||||
message GroupAttributesAccessLevelChangeUpdate {
|
||||
optional bytes updaterAci = 1;
|
||||
GroupV2AccessLevel accessLevel = 2;
|
||||
}
|
||||
|
||||
message GroupAnnouncementOnlyChangeUpdate {
|
||||
optional bytes updaterAci = 1;
|
||||
bool isAnnouncementOnly = 2;
|
||||
}
|
||||
|
||||
message GroupAdminStatusUpdate {
|
||||
optional bytes updaterAci = 1;
|
||||
// The aci who had admin status granted or revoked.
|
||||
bytes memberAci = 2;
|
||||
bool wasAdminStatusGranted = 3;
|
||||
}
|
||||
|
||||
message GroupMemberLeftUpdate {
|
||||
optional bytes aci = 1;
|
||||
}
|
||||
|
||||
message GroupMemberRemovedUpdate {
|
||||
optional bytes removerAci = 1;
|
||||
bytes removedAci = 2;
|
||||
}
|
||||
|
||||
message SelfInvitedToGroupUpdate {
|
||||
optional bytes inviterAci = 1;
|
||||
}
|
||||
|
||||
message SelfInvitedOtherUserToGroupUpdate {
|
||||
// If no invitee id available, use GroupUnknownInviteeUpdate
|
||||
bytes inviteeServiceId = 1;
|
||||
}
|
||||
|
||||
message GroupUnknownInviteeUpdate {
|
||||
// Can be the self user.
|
||||
optional bytes inviterAci = 1;
|
||||
uint32 inviteeCount = 2;
|
||||
}
|
||||
|
||||
message GroupInvitationAcceptedUpdate {
|
||||
optional bytes inviterAci = 1;
|
||||
bytes newMemberAci = 2;
|
||||
}
|
||||
|
||||
message GroupInvitationDeclinedUpdate {
|
||||
optional bytes inviterAci = 1;
|
||||
// Note: if invited by pni, just set inviteeAci to nil.
|
||||
optional bytes inviteeAci = 2;
|
||||
}
|
||||
|
||||
message GroupMemberJoinedUpdate {
|
||||
bytes newMemberAci = 1;
|
||||
}
|
||||
|
||||
message GroupMemberAddedUpdate {
|
||||
optional bytes updaterAci = 1;
|
||||
bytes newMemberAci = 2;
|
||||
bool hadOpenInvitation = 3;
|
||||
// If hadOpenInvitation is true, optionally include aci of the inviter.
|
||||
optional bytes inviterAci = 4;
|
||||
}
|
||||
|
||||
// An invitation to self was revoked.
|
||||
message GroupSelfInvitationRevokedUpdate {
|
||||
optional bytes revokerAci = 1;
|
||||
}
|
||||
|
||||
// These invitees should never be the local user.
|
||||
// Use GroupSelfInvitationRevokedUpdate in those cases.
|
||||
// The inviter or updater can be the local user.
|
||||
message GroupInvitationRevokedUpdate {
|
||||
message Invitee {
|
||||
optional bytes inviterAci = 1;
|
||||
// Prefer to use aci over pni. No need to set
|
||||
// pni if aci is set. Both can be missing.
|
||||
optional bytes inviteeAci = 2;
|
||||
optional bytes inviteePni = 3;
|
||||
}
|
||||
|
||||
// The member that revoked the invite(s), not the inviter!
|
||||
// Assumed to be an admin (at the time, may no longer be an
|
||||
// admin or even a member).
|
||||
optional bytes updaterAci = 1;
|
||||
repeated Invitee invitees = 2;
|
||||
}
|
||||
|
||||
message GroupJoinRequestUpdate {
|
||||
bytes requestorAci = 1;
|
||||
}
|
||||
|
||||
message GroupJoinRequestApprovalUpdate {
|
||||
bytes requestorAci = 1;
|
||||
// The aci that approved or rejected the request.
|
||||
optional bytes updaterAci = 2;
|
||||
bool wasApproved = 3;
|
||||
}
|
||||
|
||||
message GroupJoinRequestCanceledUpdate {
|
||||
bytes requestorAci = 1;
|
||||
}
|
||||
|
||||
// A single requestor has requested to join and cancelled
|
||||
// their request repeatedly with no other updates in between.
|
||||
// The last action encompassed by this update is always a
|
||||
// cancellation; if there was another open request immediately
|
||||
// after, it will be a separate GroupJoinRequestUpdate, either
|
||||
// in the same frame or in a subsequent frame.
|
||||
message GroupSequenceOfRequestsAndCancelsUpdate {
|
||||
bytes requestorAci = 1;
|
||||
uint32 count = 2;
|
||||
}
|
||||
|
||||
message GroupInviteLinkResetUpdate {
|
||||
optional bytes updaterAci = 1;
|
||||
}
|
||||
|
||||
message GroupInviteLinkEnabledUpdate {
|
||||
optional bytes updaterAci = 1;
|
||||
bool linkRequiresAdminApproval = 2;
|
||||
}
|
||||
|
||||
message GroupInviteLinkAdminApprovalUpdate {
|
||||
optional bytes updaterAci = 1;
|
||||
bool linkRequiresAdminApproval = 2;
|
||||
}
|
||||
|
||||
message GroupInviteLinkDisabledUpdate {
|
||||
optional bytes updaterAci = 1;
|
||||
}
|
||||
|
||||
message GroupMemberJoinedByLinkUpdate {
|
||||
bytes newMemberAci = 1;
|
||||
}
|
||||
|
||||
// A gv1->gv2 migration occurred.
|
||||
message GroupV2MigrationUpdate {}
|
||||
|
||||
// Another user migrated gv1->gv2 but was unable to add
|
||||
// the local user and invited them instead.
|
||||
message GroupV2MigrationSelfInvitedUpdate {}
|
||||
|
||||
// The local user migrated gv1->gv2 but was unable to
|
||||
// add some members and invited them instead.
|
||||
// (Happens if we don't have the invitee's profile key)
|
||||
message GroupV2MigrationInvitedMembersUpdate {
|
||||
int32 invitedMembersCount = 1;
|
||||
}
|
||||
|
||||
// The local user migrated gv1->gv2 but was unable to
|
||||
// add or invite some members and dropped them instead.
|
||||
// (Happens for e164 members where we don't have an aci).
|
||||
message GroupV2MigrationDroppedMembersUpdate {
|
||||
int32 droppedMembersCount = 1;
|
||||
}
|
||||
|
||||
message StickerPack {
|
||||
bytes id = 1;
|
||||
bytes key = 2;
|
||||
|
|
|
@ -11,6 +11,8 @@ package signal;
|
|||
option java_package = "org.thoughtcrime.securesms.database.model.databaseprotos";
|
||||
option java_multiple_files = true;
|
||||
|
||||
import Backup.proto;
|
||||
|
||||
// DEPRECATED -- only here for database migrations
|
||||
message ReactionList {
|
||||
option deprecated = true;
|
||||
|
@ -371,3 +373,12 @@ message ExternalLaunchTransactionState {
|
|||
GatewayRequest gatewayRequest = 2;
|
||||
string paymentSourceType = 3;
|
||||
}
|
||||
|
||||
message MessageExtras {
|
||||
GV2UpdateDescription gv2UpdateDescription = 1;
|
||||
}
|
||||
|
||||
message GV2UpdateDescription {
|
||||
optional DecryptedGroupV2Context gv2ChangeDescription = 1;
|
||||
backup.GroupChangeChatUpdate groupChangeUpdate = 2;
|
||||
}
|
|
@ -183,7 +183,8 @@ object FakeMessageRecords {
|
|||
null,
|
||||
null,
|
||||
0,
|
||||
false
|
||||
false,
|
||||
null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue