mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-22 18:00:02 +01:00
Add GV2 accept by PNI invite.
This commit is contained in:
@@ -83,6 +83,9 @@ public class GroupDatabase extends Database {
|
||||
private static final String UNMIGRATED_V1_MEMBERS = "former_v1_members";
|
||||
private static final String DISTRIBUTION_ID = "distribution_id";
|
||||
private static final String DISPLAY_AS_STORY = "display_as_story";
|
||||
|
||||
/** Was temporarily used for PNP accept by pni but is no longer needed/updated */
|
||||
@Deprecated
|
||||
private static final String AUTH_SERVICE_ID = "auth_service_id";
|
||||
|
||||
|
||||
@@ -125,7 +128,7 @@ public class GroupDatabase extends Database {
|
||||
|
||||
private static final String[] GROUP_PROJECTION = {
|
||||
GROUP_ID, RECIPIENT_ID, TITLE, MEMBERS, UNMIGRATED_V1_MEMBERS, AVATAR_ID, AVATAR_KEY, AVATAR_CONTENT_TYPE, AVATAR_RELAY, AVATAR_DIGEST,
|
||||
TIMESTAMP, ACTIVE, MMS, V2_MASTER_KEY, V2_REVISION, V2_DECRYPTED_GROUP, AUTH_SERVICE_ID
|
||||
TIMESTAMP, ACTIVE, MMS, V2_MASTER_KEY, V2_REVISION, V2_DECRYPTED_GROUP
|
||||
};
|
||||
|
||||
static final List<String> TYPED_GROUP_PROJECTION = Stream.of(GROUP_PROJECTION).map(columnName -> TABLE_NAME + "." + columnName).toList();
|
||||
@@ -477,25 +480,23 @@ public class GroupDatabase extends Database {
|
||||
if (groupExists(groupId.deriveV2MigrationGroupId())) {
|
||||
throw new LegacyGroupInsertException(groupId);
|
||||
}
|
||||
create(null, groupId, title, members, avatar, relay, null, null);
|
||||
create(groupId, title, members, avatar, relay, null, null);
|
||||
}
|
||||
|
||||
public void create(@NonNull GroupId.Mms groupId,
|
||||
@Nullable String title,
|
||||
@NonNull Collection<RecipientId> members)
|
||||
{
|
||||
create(null, groupId, Util.isEmpty(title) ? null : title, members, null, null, null, null);
|
||||
create(groupId, Util.isEmpty(title) ? null : title, members, null, null, null, null);
|
||||
}
|
||||
|
||||
public GroupId.V2 create(@Nullable ServiceId authServiceId,
|
||||
@NonNull GroupMasterKey groupMasterKey,
|
||||
public GroupId.V2 create(@NonNull GroupMasterKey groupMasterKey,
|
||||
@NonNull DecryptedGroup groupState)
|
||||
{
|
||||
return create(authServiceId, groupMasterKey, groupState, false);
|
||||
return create(groupMasterKey, groupState, false);
|
||||
}
|
||||
|
||||
public GroupId.V2 create(@Nullable ServiceId authServiceId,
|
||||
@NonNull GroupMasterKey groupMasterKey,
|
||||
public GroupId.V2 create(@NonNull GroupMasterKey groupMasterKey,
|
||||
@NonNull DecryptedGroup groupState,
|
||||
boolean force)
|
||||
{
|
||||
@@ -507,7 +508,7 @@ public class GroupDatabase extends Database {
|
||||
Log.w(TAG, "Forcing the creation of a group even though we already have a V1 ID!");
|
||||
}
|
||||
|
||||
create(authServiceId, groupId, groupState.getTitle(), Collections.emptyList(), null, null, groupMasterKey, groupState);
|
||||
create(groupId, groupState.getTitle(), Collections.emptyList(), null, null, groupMasterKey, groupState);
|
||||
|
||||
return groupId;
|
||||
}
|
||||
@@ -537,8 +538,8 @@ public class GroupDatabase extends Database {
|
||||
|
||||
if (updated < 1) {
|
||||
Log.w(TAG, "No group entry. Creating restore placeholder for " + groupId);
|
||||
create(authServiceId,
|
||||
groupMasterKey,
|
||||
create(
|
||||
groupMasterKey,
|
||||
DecryptedGroup.newBuilder()
|
||||
.setRevision(GroupsV2StateProcessor.RESTORE_PLACEHOLDER_REVISION)
|
||||
.build(),
|
||||
@@ -559,8 +560,7 @@ public class GroupDatabase extends Database {
|
||||
/**
|
||||
* @param groupMasterKey null for V1, must be non-null for V2 (presence dictates group version).
|
||||
*/
|
||||
private void create(@Nullable ServiceId authServiceId,
|
||||
@NonNull GroupId groupId,
|
||||
private void create(@NonNull GroupId groupId,
|
||||
@Nullable String title,
|
||||
@NonNull Collection<RecipientId> memberCollection,
|
||||
@Nullable SignalServiceAttachmentPointer avatar,
|
||||
@@ -575,7 +575,6 @@ public class GroupDatabase extends Database {
|
||||
Collections.sort(members);
|
||||
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(AUTH_SERVICE_ID, authServiceId != null ? authServiceId.toString() : null);
|
||||
contentValues.put(RECIPIENT_ID, groupRecipientId.serialize());
|
||||
contentValues.put(GROUP_ID, groupId.toString());
|
||||
contentValues.put(TITLE, title);
|
||||
@@ -987,13 +986,6 @@ public class GroupDatabase extends Database {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setAuthServiceId(@Nullable ServiceId authServiceId, @NonNull GroupId groupId) {
|
||||
ContentValues values = new ContentValues(1);
|
||||
values.put(AUTH_SERVICE_ID, authServiceId == null ? null : authServiceId.toString());
|
||||
|
||||
getWritableDatabase().update(TABLE_NAME, values, GROUP_ID + " = ?", SqlUtil.buildArgs(groupId));
|
||||
}
|
||||
|
||||
public static class Reader implements Closeable {
|
||||
|
||||
public final Cursor cursor;
|
||||
@@ -1038,8 +1030,7 @@ public class GroupDatabase extends Database {
|
||||
CursorUtil.requireBlob(cursor, V2_MASTER_KEY),
|
||||
CursorUtil.requireInt(cursor, V2_REVISION),
|
||||
CursorUtil.requireBlob(cursor, V2_DECRYPTED_GROUP),
|
||||
CursorUtil.getString(cursor, DISTRIBUTION_ID).map(DistributionId::from).orElse(null),
|
||||
CursorUtil.requireString(cursor, AUTH_SERVICE_ID));
|
||||
CursorUtil.getString(cursor, DISTRIBUTION_ID).map(DistributionId::from).orElse(null));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1065,7 +1056,6 @@ public class GroupDatabase extends Database {
|
||||
private final boolean mms;
|
||||
@Nullable private final V2GroupProperties v2GroupProperties;
|
||||
private final DistributionId distributionId;
|
||||
@Nullable private final String authServiceId;
|
||||
|
||||
public GroupRecord(@NonNull GroupId id,
|
||||
@NonNull RecipientId recipientId,
|
||||
@@ -1082,8 +1072,7 @@ public class GroupDatabase extends Database {
|
||||
@Nullable byte[] groupMasterKeyBytes,
|
||||
int groupRevision,
|
||||
@Nullable byte[] decryptedGroupBytes,
|
||||
@Nullable DistributionId distributionId,
|
||||
@Nullable String authServiceId)
|
||||
@Nullable DistributionId distributionId)
|
||||
{
|
||||
this.id = id;
|
||||
this.recipientId = recipientId;
|
||||
@@ -1096,7 +1085,6 @@ public class GroupDatabase extends Database {
|
||||
this.active = active;
|
||||
this.mms = mms;
|
||||
this.distributionId = distributionId;
|
||||
this.authServiceId = authServiceId;
|
||||
|
||||
V2GroupProperties v2GroupProperties = null;
|
||||
if (groupMasterKeyBytes != null && decryptedGroupBytes != null) {
|
||||
@@ -1285,10 +1273,6 @@ public class GroupDatabase extends Database {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public @Nullable ServiceId getAuthServiceId() {
|
||||
return ServiceId.parseOrNull(authServiceId);
|
||||
}
|
||||
}
|
||||
|
||||
public static class V2GroupProperties {
|
||||
|
||||
@@ -33,8 +33,8 @@ import org.signal.core.util.withinTransaction
|
||||
import org.signal.libsignal.protocol.IdentityKey
|
||||
import org.signal.libsignal.protocol.InvalidKeyException
|
||||
import org.signal.libsignal.zkgroup.InvalidInputException
|
||||
import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKeyCredential
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup
|
||||
import org.thoughtcrime.securesms.badges.Badges
|
||||
import org.thoughtcrime.securesms.badges.Badges.toDatabaseBadge
|
||||
@@ -66,7 +66,7 @@ import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BadgeList
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ChatColor
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.DeviceLastResetTime
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ProfileKeyCredentialColumnData
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ExpiringProfileKeyCredentialColumnData
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.RecipientExtras
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.Wallpaper
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
@@ -154,7 +154,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
private const val SYSTEM_CONTACT_URI = "system_contact_uri"
|
||||
private const val SYSTEM_INFO_PENDING = "system_info_pending"
|
||||
private const val PROFILE_KEY = "profile_key"
|
||||
private const val PROFILE_KEY_CREDENTIAL = "profile_key_credential"
|
||||
const val EXPIRING_PROFILE_KEY_CREDENTIAL = "profile_key_credential"
|
||||
private const val SIGNAL_PROFILE_AVATAR = "signal_profile_avatar"
|
||||
const val PROFILE_SHARING = "profile_sharing"
|
||||
private const val LAST_PROFILE_FETCH = "last_profile_fetch"
|
||||
@@ -214,7 +214,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
$SYSTEM_CONTACT_URI TEXT DEFAULT NULL,
|
||||
$SYSTEM_INFO_PENDING INTEGER DEFAULT 0,
|
||||
$PROFILE_KEY TEXT DEFAULT NULL,
|
||||
$PROFILE_KEY_CREDENTIAL TEXT DEFAULT NULL,
|
||||
$EXPIRING_PROFILE_KEY_CREDENTIAL TEXT DEFAULT NULL,
|
||||
$PROFILE_GIVEN_NAME TEXT DEFAULT NULL,
|
||||
$PROFILE_FAMILY_NAME TEXT DEFAULT NULL,
|
||||
$PROFILE_JOINED_NAME TEXT DEFAULT NULL,
|
||||
@@ -269,7 +269,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
MESSAGE_EXPIRATION_TIME,
|
||||
REGISTERED,
|
||||
PROFILE_KEY,
|
||||
PROFILE_KEY_CREDENTIAL,
|
||||
EXPIRING_PROFILE_KEY_CREDENTIAL,
|
||||
SYSTEM_JOINED_NAME,
|
||||
SYSTEM_GIVEN_NAME,
|
||||
SYSTEM_FAMILY_NAME,
|
||||
@@ -925,7 +925,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
val recipientId = getByStorageKeyOrThrow(update.new.id.raw)
|
||||
if (StorageSyncHelper.profileKeyChanged(update)) {
|
||||
val clearValues = ContentValues(1).apply {
|
||||
putNull(PROFILE_KEY_CREDENTIAL)
|
||||
putNull(EXPIRING_PROFILE_KEY_CREDENTIAL)
|
||||
}
|
||||
db.update(TABLE_NAME, clearValues, ID_WHERE, SqlUtil.buildArgs(recipientId))
|
||||
}
|
||||
@@ -986,7 +986,6 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
|
||||
Log.i(TAG, "Creating restore placeholder for $groupId")
|
||||
groups.create(
|
||||
null,
|
||||
masterKey,
|
||||
DecryptedGroup.newBuilder()
|
||||
.setRevision(GroupsV2StateProcessor.RESTORE_PLACEHOLDER_REVISION)
|
||||
@@ -1560,7 +1559,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
}
|
||||
val valuesToSet = ContentValues(3).apply {
|
||||
put(PROFILE_KEY, encodedProfileKey)
|
||||
putNull(PROFILE_KEY_CREDENTIAL)
|
||||
putNull(EXPIRING_PROFILE_KEY_CREDENTIAL)
|
||||
put(UNIDENTIFIED_ACCESS_MODE, UnidentifiedAccessMode.UNKNOWN.mode)
|
||||
}
|
||||
|
||||
@@ -1592,7 +1591,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
val args = arrayOf(id.serialize())
|
||||
val valuesToSet = ContentValues(3).apply {
|
||||
put(PROFILE_KEY, Base64.encodeBytes(profileKey.serialize()))
|
||||
putNull(PROFILE_KEY_CREDENTIAL)
|
||||
putNull(EXPIRING_PROFILE_KEY_CREDENTIAL)
|
||||
put(UNIDENTIFIED_ACCESS_MODE, UnidentifiedAccessMode.UNKNOWN.mode)
|
||||
}
|
||||
|
||||
@@ -1611,16 +1610,16 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
fun setProfileKeyCredential(
|
||||
id: RecipientId,
|
||||
profileKey: ProfileKey,
|
||||
profileKeyCredential: ProfileKeyCredential
|
||||
expiringProfileKeyCredential: ExpiringProfileKeyCredential
|
||||
): Boolean {
|
||||
val selection = "$ID = ? AND $PROFILE_KEY = ?"
|
||||
val args = arrayOf(id.serialize(), Base64.encodeBytes(profileKey.serialize()))
|
||||
val columnData = ProfileKeyCredentialColumnData.newBuilder()
|
||||
val columnData = ExpiringProfileKeyCredentialColumnData.newBuilder()
|
||||
.setProfileKey(ByteString.copyFrom(profileKey.serialize()))
|
||||
.setProfileKeyCredential(ByteString.copyFrom(profileKeyCredential.serialize()))
|
||||
.setExpiringProfileKeyCredential(ByteString.copyFrom(expiringProfileKeyCredential.serialize()))
|
||||
.build()
|
||||
val values = ContentValues(1).apply {
|
||||
put(PROFILE_KEY_CREDENTIAL, Base64.encodeBytes(columnData.toByteArray()))
|
||||
put(EXPIRING_PROFILE_KEY_CREDENTIAL, Base64.encodeBytes(columnData.toByteArray()))
|
||||
}
|
||||
val updateQuery = SqlUtil.buildTrueUpdateQuery(selection, args, values)
|
||||
|
||||
@@ -1634,11 +1633,8 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
|
||||
fun clearProfileKeyCredential(id: RecipientId) {
|
||||
val values = ContentValues(1)
|
||||
values.putNull(PROFILE_KEY_CREDENTIAL)
|
||||
values.putNull(PROFILE_KEY)
|
||||
values.put(PROFILE_SHARING, 0)
|
||||
values.putNull(EXPIRING_PROFILE_KEY_CREDENTIAL)
|
||||
if (update(id, values)) {
|
||||
rotateStorageId(id)
|
||||
ApplicationDependencies.getDatabaseObserver().notifyRecipientChanged(id)
|
||||
}
|
||||
}
|
||||
@@ -2101,11 +2097,11 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
|
||||
db.beginTransaction()
|
||||
try {
|
||||
for ((recipientId, aci) in registered) {
|
||||
for ((recipientId, serviceId) in registered) {
|
||||
val values = ContentValues(2).apply {
|
||||
put(REGISTERED, RegisteredState.REGISTERED.id)
|
||||
if (aci != null) {
|
||||
put(SERVICE_ID, aci.toString().lowercase())
|
||||
if (serviceId != null) {
|
||||
put(SERVICE_ID, serviceId.toString().lowercase())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2117,7 +2113,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
} catch (e: SQLiteConstraintException) {
|
||||
Log.w(TAG, "[bulkUpdateRegisteredStatus] Hit a conflict when trying to update $recipientId. Possibly merging.")
|
||||
val e164 = getRecord(recipientId).e164
|
||||
val newId = getAndPossiblyMerge(aci, e164)
|
||||
val newId = getAndPossiblyMerge(serviceId, e164)
|
||||
Log.w(TAG, "[bulkUpdateRegisteredStatus] Merged into $newId")
|
||||
}
|
||||
}
|
||||
@@ -2173,7 +2169,8 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes CDSv2 results, merging recipients as necessary.
|
||||
* Processes CDSv2 results, merging recipients as necessary. Does not mark users as
|
||||
* registered.
|
||||
*
|
||||
* Important: This is under active development and is not suitable for actual use.
|
||||
*
|
||||
@@ -3489,6 +3486,9 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
}
|
||||
}
|
||||
.run()
|
||||
|
||||
ApplicationDependencies.getRecipientCache().clear()
|
||||
RecipientId.clearCache()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3499,7 +3499,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
.update(TABLE_NAME)
|
||||
.values(
|
||||
PROFILE_KEY to null,
|
||||
PROFILE_KEY_CREDENTIAL to null,
|
||||
EXPIRING_PROFILE_KEY_CREDENTIAL to null,
|
||||
PROFILE_GIVEN_NAME to null,
|
||||
PROFILE_FAMILY_NAME to null,
|
||||
PROFILE_JOINED_NAME to null,
|
||||
@@ -3514,6 +3514,9 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
}
|
||||
}
|
||||
.run()
|
||||
|
||||
ApplicationDependencies.getRecipientCache().clear()
|
||||
RecipientId.clearCache()
|
||||
}
|
||||
|
||||
fun getRecord(context: Context, cursor: Cursor): RecipientRecord {
|
||||
@@ -3522,9 +3525,9 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
|
||||
fun getRecord(context: Context, cursor: Cursor, idColumnName: String): RecipientRecord {
|
||||
val profileKeyString = cursor.requireString(PROFILE_KEY)
|
||||
val profileKeyCredentialString = cursor.requireString(PROFILE_KEY_CREDENTIAL)
|
||||
val expiringProfileKeyCredentialString = cursor.requireString(EXPIRING_PROFILE_KEY_CREDENTIAL)
|
||||
var profileKey: ByteArray? = null
|
||||
var profileKeyCredential: ProfileKeyCredential? = null
|
||||
var expiringProfileKeyCredential: ExpiringProfileKeyCredential? = null
|
||||
|
||||
if (profileKeyString != null) {
|
||||
try {
|
||||
@@ -3533,12 +3536,12 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
Log.w(TAG, e)
|
||||
}
|
||||
|
||||
if (profileKeyCredentialString != null) {
|
||||
if (expiringProfileKeyCredentialString != null) {
|
||||
try {
|
||||
val columnDataBytes = Base64.decode(profileKeyCredentialString)
|
||||
val columnData = ProfileKeyCredentialColumnData.parseFrom(columnDataBytes)
|
||||
val columnDataBytes = Base64.decode(expiringProfileKeyCredentialString)
|
||||
val columnData = ExpiringProfileKeyCredentialColumnData.parseFrom(columnDataBytes)
|
||||
if (Arrays.equals(columnData.profileKey.toByteArray(), profileKey)) {
|
||||
profileKeyCredential = ProfileKeyCredential(columnData.profileKeyCredential.toByteArray())
|
||||
expiringProfileKeyCredential = ExpiringProfileKeyCredential(columnData.expiringProfileKeyCredential.toByteArray())
|
||||
} else {
|
||||
Log.i(TAG, "Out of date profile key credential data ignored on read")
|
||||
}
|
||||
@@ -3598,7 +3601,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
expireMessages = cursor.requireInt(MESSAGE_EXPIRATION_TIME),
|
||||
registered = RegisteredState.fromId(cursor.requireInt(REGISTERED)),
|
||||
profileKey = profileKey,
|
||||
profileKeyCredential = profileKeyCredential,
|
||||
expiringProfileKeyCredential = expiringProfileKeyCredential,
|
||||
systemProfileName = ProfileName.fromParts(cursor.requireString(SYSTEM_GIVEN_NAME), cursor.requireString(SYSTEM_FAMILY_NAME)),
|
||||
systemDisplayName = cursor.requireString(SYSTEM_JOINED_NAME),
|
||||
systemContactPhotoUri = cursor.requireString(SYSTEM_PHOTO_URI),
|
||||
@@ -3688,7 +3691,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
private fun updateProfileValuesForMerge(values: ContentValues, record: RecipientRecord) {
|
||||
values.apply {
|
||||
put(PROFILE_KEY, if (record.profileKey != null) Base64.encodeBytes(record.profileKey) else null)
|
||||
putNull(PROFILE_KEY_CREDENTIAL)
|
||||
putNull(EXPIRING_PROFILE_KEY_CREDENTIAL)
|
||||
put(SIGNAL_PROFILE_AVATAR, record.signalProfileAvatar)
|
||||
put(PROFILE_GIVEN_NAME, record.signalProfileName.givenName)
|
||||
put(PROFILE_FAMILY_NAME, record.signalProfileName.familyName)
|
||||
|
||||
@@ -202,8 +202,9 @@ object SignalDatabaseMigrations {
|
||||
private const val REMOTE_MEGAPHONE = 146
|
||||
private const val QUOTE_INDEX = 147
|
||||
private const val MY_STORY_PRIVACY_MODE = 148
|
||||
private const val EXPIRING_PROFILE_CREDENTIALS = 149
|
||||
|
||||
const val DATABASE_VERSION = 148
|
||||
const val DATABASE_VERSION = 149
|
||||
|
||||
@JvmStatic
|
||||
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
@@ -2658,6 +2659,10 @@ object SignalDatabaseMigrations {
|
||||
|
||||
db.execSQL("CREATE UNIQUE INDEX distribution_list_member_list_id_recipient_id_privacy_mode_index ON distribution_list_member (list_id, recipient_id, privacy_mode)")
|
||||
}
|
||||
|
||||
if (oldVersion < EXPIRING_PROFILE_CREDENTIALS) {
|
||||
db.execSQL("UPDATE recipient SET profile_key_credential = NULL")
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
||||
@@ -28,13 +28,13 @@ 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.groups.GV2AccessLevelUtil;
|
||||
import org.thoughtcrime.securesms.keyvalue.ServiceIds;
|
||||
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.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceIds;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -91,8 +91,8 @@ final class GroupsV2UpdateMessageProducer {
|
||||
}
|
||||
|
||||
if (DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfIds.getAci().uuid()).isPresent() ||
|
||||
(selfIds.getPni() != null && DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfIds.getPni().uuid()).isPresent())
|
||||
) {
|
||||
(selfIds.getPni() != null && DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfIds.getPni().uuid()).isPresent()))
|
||||
{
|
||||
return updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_16);
|
||||
} else {
|
||||
return updateDescription(context.getString(R.string.MessageRecord_group_updated), R.drawable.ic_update_group_16);
|
||||
@@ -124,6 +124,7 @@ final class GroupsV2UpdateMessageProducer {
|
||||
describeUnknownEditorRequestingMembersApprovals(change, updates);
|
||||
describeUnknownEditorRequestingMembersDeletes(change, updates);
|
||||
describeUnknownEditorAnnouncementGroupChange(change, updates);
|
||||
describeUnknownEditorPromotePendingPniAci(change, updates);
|
||||
|
||||
describeUnknownEditorMemberRemovals(change, updates);
|
||||
|
||||
@@ -149,6 +150,7 @@ final class GroupsV2UpdateMessageProducer {
|
||||
describeRequestingMembersApprovals(change, updates);
|
||||
describeRequestingMembersDeletes(change, updates);
|
||||
describeAnnouncementGroupChange(change, updates);
|
||||
describePromotePendingPniAci(change, updates);
|
||||
|
||||
describeMemberRemovals(change, updates);
|
||||
|
||||
@@ -304,8 +306,8 @@ final class GroupsV2UpdateMessageProducer {
|
||||
}
|
||||
|
||||
private void describeInvitations(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
|
||||
boolean editorIsYou = selfIds.matches(change.getEditor());
|
||||
int notYouInviteCount = 0;
|
||||
boolean editorIsYou = selfIds.matches(change.getEditor());
|
||||
int notYouInviteCount = 0;
|
||||
|
||||
for (DecryptedPendingMember invitee : change.getNewPendingMembersList()) {
|
||||
boolean newMemberIsYou = selfIds.matches(invitee.getUuid());
|
||||
@@ -351,8 +353,8 @@ final class GroupsV2UpdateMessageProducer {
|
||||
}
|
||||
|
||||
private void describeRevokedInvitations(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
|
||||
boolean editorIsYou = selfIds.matches(change.getEditor());
|
||||
int notDeclineCount = 0;
|
||||
boolean editorIsYou = selfIds.matches(change.getEditor());
|
||||
int notDeclineCount = 0;
|
||||
|
||||
for (DecryptedPendingMemberRemoval invitee : change.getDeletePendingMembersList()) {
|
||||
boolean decline = invitee.getUuid().equals(change.getEditor());
|
||||
@@ -400,8 +402,8 @@ final class GroupsV2UpdateMessageProducer {
|
||||
boolean editorIsYou = selfIds.matches(change.getEditor());
|
||||
|
||||
for (DecryptedMember newMember : change.getPromotePendingMembersList()) {
|
||||
ByteString uuid = newMember.getUuid();
|
||||
boolean newMemberIsYou = selfIds.matches(uuid);
|
||||
ByteString uuid = newMember.getUuid();
|
||||
boolean newMemberIsYou = selfIds.matches(uuid);
|
||||
|
||||
if (editorIsYou) {
|
||||
if (newMemberIsYou) {
|
||||
@@ -425,8 +427,8 @@ final class GroupsV2UpdateMessageProducer {
|
||||
|
||||
private void describeUnknownEditorPromotePending(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
|
||||
for (DecryptedMember newMember : change.getPromotePendingMembersList()) {
|
||||
ByteString uuid = newMember.getUuid();
|
||||
boolean newMemberIsYou = selfIds.matches(uuid);
|
||||
ByteString uuid = newMember.getUuid();
|
||||
boolean newMemberIsYou = selfIds.matches(uuid);
|
||||
|
||||
if (newMemberIsYou) {
|
||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_16));
|
||||
@@ -679,7 +681,7 @@ final class GroupsV2UpdateMessageProducer {
|
||||
if (requestingMemberIsYou) {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_approved_your_request_to_join_the_group, change.getEditor(), R.drawable.ic_update_group_accept_16));
|
||||
} else {
|
||||
boolean editorIsYou = selfIds.matches(change.getEditor());
|
||||
boolean editorIsYou = selfIds.matches(change.getEditor());
|
||||
|
||||
if (editorIsYou) {
|
||||
updates.add(updateDescription(R.string.MessageRecord_you_approved_a_request_to_join_the_group_from_s, requestingMember.getUuid(), R.drawable.ic_update_group_accept_16));
|
||||
@@ -770,6 +772,46 @@ final class GroupsV2UpdateMessageProducer {
|
||||
}
|
||||
}
|
||||
|
||||
private void describePromotePendingPniAci(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
|
||||
boolean editorIsYou = selfIds.matches(change.getEditor());
|
||||
|
||||
for (DecryptedMember newMember : change.getPromotePendingPniAciMembersList()) {
|
||||
ByteString uuid = newMember.getUuid();
|
||||
boolean newMemberIsYou = selfIds.matches(uuid);
|
||||
|
||||
if (editorIsYou) {
|
||||
if (newMemberIsYou) {
|
||||
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_you_added_invited_member_s, uuid, R.drawable.ic_update_group_add_16));
|
||||
}
|
||||
} else {
|
||||
if (newMemberIsYou) {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_added_you, change.getEditor(), R.drawable.ic_update_group_add_16));
|
||||
} else {
|
||||
if (uuid.equals(change.getEditor())) {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_accepted_invite, uuid, R.drawable.ic_update_group_accept_16));
|
||||
} else {
|
||||
updates.add(updateDescription(R.string.MessageRecord_s_added_invited_member_s, change.getEditor(), uuid, R.drawable.ic_update_group_add_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void describeUnknownEditorPromotePendingPniAci(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
|
||||
for (DecryptedMember newMember : change.getPromotePendingPniAciMembersList()) {
|
||||
ByteString uuid = newMember.getUuid();
|
||||
boolean newMemberIsYou = selfIds.matches(uuid);
|
||||
|
||||
if (newMemberIsYou) {
|
||||
updates.add(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, uuid, R.drawable.ic_update_group_add_16));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static UpdateDescription updateDescription(@NonNull String string, @DrawableRes int iconResource) {
|
||||
return UpdateDescription.staticDescription(string, iconResource);
|
||||
}
|
||||
@@ -868,8 +910,8 @@ final class GroupsV2UpdateMessageProducer {
|
||||
|
||||
@VisibleForTesting
|
||||
static @NonNull Spannable makeRecipientsClickable(@NonNull Context context, @NonNull String template, @NonNull List<RecipientId> recipientIds, @Nullable Consumer<RecipientId> clickHandler) {
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder();
|
||||
int startIndex = 0;
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder();
|
||||
int startIndex = 0;
|
||||
|
||||
Map<String, RecipientId> idByPlaceholder = new HashMap<>();
|
||||
for (RecipientId id : recipientIds) {
|
||||
|
||||
@@ -2,7 +2,7 @@ package org.thoughtcrime.securesms.database.model
|
||||
|
||||
import android.net.Uri
|
||||
import org.signal.libsignal.zkgroup.groups.GroupMasterKey
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKeyCredential
|
||||
import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential
|
||||
import org.thoughtcrime.securesms.badges.models.Badge
|
||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColors
|
||||
@@ -45,7 +45,7 @@ data class RecipientRecord(
|
||||
val expireMessages: Int,
|
||||
val registered: RegisteredState,
|
||||
val profileKey: ByteArray?,
|
||||
val profileKeyCredential: ProfileKeyCredential?,
|
||||
val expiringProfileKeyCredential: ExpiringProfileKeyCredential?,
|
||||
val systemProfileName: ProfileName,
|
||||
val systemDisplayName: String?,
|
||||
val systemContactPhotoUri: String?,
|
||||
|
||||
Reference in New Issue
Block a user