mirror of
https://github.com/oxen-io/session-android.git
synced 2025-08-27 08:17:50 +00:00
Refactor how we handle GV1->GV2 migration suggestions.
This commit is contained in:
@@ -16,7 +16,7 @@ public class GroupsV1MigrationSuggestionsReminder extends Reminder {
|
||||
public GroupsV1MigrationSuggestionsReminder(@NonNull Context context, @NonNull List<RecipientId> suggestions) {
|
||||
super(null, context.getResources().getQuantityString(R.plurals.GroupsV1MigrationSuggestionsReminder_members_couldnt_be_added_to_the_new_group, suggestions.size(), suggestions.size()));
|
||||
addAction(new Action(context.getResources().getQuantityString(R.plurals.GroupsV1MigrationSuggestionsReminder_add_members, suggestions.size()), R.id.reminder_action_gv1_suggestion_add_members));
|
||||
addAction(new Action(context.getResources().getString(R.string.GroupsV1MigrationSuggestionsReminder_not_now), R.id.reminder_action_gv1_suggestion_not_now));
|
||||
addAction(new Action(context.getResources().getString(R.string.GroupsV1MigrationSuggestionsReminder_no_thanks), R.id.reminder_action_gv1_suggestion_no_thanks));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -1782,8 +1782,8 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
||||
reminderView.get().setOnActionClickListener(actionId -> {
|
||||
if (actionId == R.id.reminder_action_gv1_suggestion_add_members) {
|
||||
GroupsV1MigrationSuggestionsDialog.show(this, recipient.get().requireGroupId().requireV2(), gv1MigrationSuggestions);
|
||||
} else if (actionId == R.id.reminder_action_gv1_suggestion_not_now) {
|
||||
groupViewModel.onSuggestedMembersBannerDismissed(recipient.get().requireGroupId());
|
||||
} else if (actionId == R.id.reminder_action_gv1_suggestion_no_thanks) {
|
||||
groupViewModel.onSuggestedMembersBannerDismissed(recipient.get().requireGroupId(), gv1MigrationSuggestions);
|
||||
}
|
||||
});
|
||||
reminderView.get().setOnDismissListener(() -> {
|
||||
|
@@ -31,13 +31,11 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.util.AsynchronousCallback;
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||
import org.thoughtcrime.securesms.util.SetUtil;
|
||||
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
final class ConversationGroupViewModel extends ViewModel {
|
||||
@@ -83,10 +81,10 @@ final class ConversationGroupViewModel extends ViewModel {
|
||||
liveRecipient.setValue(recipient);
|
||||
}
|
||||
|
||||
void onSuggestedMembersBannerDismissed(@NonNull GroupId groupId) {
|
||||
void onSuggestedMembersBannerDismissed(@NonNull GroupId groupId, @NonNull List<RecipientId> suggestions) {
|
||||
SignalExecutors.BOUNDED.execute(() -> {
|
||||
if (groupId.isV2()) {
|
||||
DatabaseFactory.getGroupDatabase(ApplicationDependencies.getApplication()).clearFormerV1Members(groupId.requireV2());
|
||||
DatabaseFactory.getGroupDatabase(ApplicationDependencies.getApplication()).removeUnmigratedV1Members(groupId.requireV2(), suggestions);
|
||||
liveRecipient.postValue(liveRecipient.getValue());
|
||||
}
|
||||
});
|
||||
@@ -177,9 +175,9 @@ final class ConversationGroupViewModel extends ViewModel {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Set<RecipientId> difference = SetUtil.difference(record.getFormerV1Members(), record.getMembers());
|
||||
|
||||
return Stream.of(Recipient.resolvedList(difference))
|
||||
return Stream.of(record.getUnmigratedV1Members())
|
||||
.filterNot(m -> record.getMembers().contains(m))
|
||||
.map(Recipient::resolved)
|
||||
.filter(GroupsV1MigrationUtil::isAutoMigratable)
|
||||
.map(Recipient::getId)
|
||||
.toList();
|
||||
|
@@ -15,8 +15,10 @@ import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.storageservice.protos.groups.AccessControl;
|
||||
import org.signal.storageservice.protos.groups.GroupChange;
|
||||
import org.signal.storageservice.protos.groups.Member;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedMember;
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.groups.GroupMasterKey;
|
||||
@@ -33,6 +35,7 @@ import org.thoughtcrime.securesms.util.SqlUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupChangeReconstruct;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
@@ -47,6 +50,7 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@Trace
|
||||
@@ -54,22 +58,22 @@ public final class GroupDatabase extends Database {
|
||||
|
||||
private static final String TAG = Log.tag(GroupDatabase.class);
|
||||
|
||||
static final String TABLE_NAME = "groups";
|
||||
private static final String ID = "_id";
|
||||
static final String GROUP_ID = "group_id";
|
||||
static final String RECIPIENT_ID = "recipient_id";
|
||||
private static final String TITLE = "title";
|
||||
static final String MEMBERS = "members";
|
||||
private static final String AVATAR_ID = "avatar_id";
|
||||
private static final String AVATAR_KEY = "avatar_key";
|
||||
private static final String AVATAR_CONTENT_TYPE = "avatar_content_type";
|
||||
private static final String AVATAR_RELAY = "avatar_relay";
|
||||
private static final String AVATAR_DIGEST = "avatar_digest";
|
||||
private static final String TIMESTAMP = "timestamp";
|
||||
static final String ACTIVE = "active";
|
||||
static final String MMS = "mms";
|
||||
private static final String EXPECTED_V2_ID = "expected_v2_id";
|
||||
private static final String FORMER_V1_MEMBERS = "former_v1_members";
|
||||
static final String TABLE_NAME = "groups";
|
||||
private static final String ID = "_id";
|
||||
static final String GROUP_ID = "group_id";
|
||||
static final String RECIPIENT_ID = "recipient_id";
|
||||
private static final String TITLE = "title";
|
||||
static final String MEMBERS = "members";
|
||||
private static final String AVATAR_ID = "avatar_id";
|
||||
private static final String AVATAR_KEY = "avatar_key";
|
||||
private static final String AVATAR_CONTENT_TYPE = "avatar_content_type";
|
||||
private static final String AVATAR_RELAY = "avatar_relay";
|
||||
private static final String AVATAR_DIGEST = "avatar_digest";
|
||||
private static final String TIMESTAMP = "timestamp";
|
||||
static final String ACTIVE = "active";
|
||||
static final String MMS = "mms";
|
||||
private static final String EXPECTED_V2_ID = "expected_v2_id";
|
||||
private static final String UNMIGRATED_V1_MEMBERS = "former_v1_members";
|
||||
|
||||
|
||||
/* V2 Group columns */
|
||||
@@ -80,24 +84,24 @@ public final class GroupDatabase extends Database {
|
||||
/** Serialized {@link DecryptedGroup} protobuf */
|
||||
private static final String V2_DECRYPTED_GROUP = "decrypted_group";
|
||||
|
||||
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY, " +
|
||||
GROUP_ID + " TEXT, " +
|
||||
RECIPIENT_ID + " INTEGER, " +
|
||||
TITLE + " TEXT, " +
|
||||
MEMBERS + " TEXT, " +
|
||||
AVATAR_ID + " INTEGER, " +
|
||||
AVATAR_KEY + " BLOB, " +
|
||||
AVATAR_CONTENT_TYPE + " TEXT, " +
|
||||
AVATAR_RELAY + " TEXT, " +
|
||||
TIMESTAMP + " INTEGER, " +
|
||||
ACTIVE + " INTEGER DEFAULT 1, " +
|
||||
AVATAR_DIGEST + " BLOB, " +
|
||||
MMS + " INTEGER DEFAULT 0, " +
|
||||
V2_MASTER_KEY + " BLOB, " +
|
||||
V2_REVISION + " BLOB, " +
|
||||
V2_DECRYPTED_GROUP + " BLOB, " +
|
||||
EXPECTED_V2_ID + " TEXT DEFAULT NULL, " +
|
||||
FORMER_V1_MEMBERS + " TEXT DEFAULT NULL);";
|
||||
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY, " +
|
||||
GROUP_ID + " TEXT, " +
|
||||
RECIPIENT_ID + " INTEGER, " +
|
||||
TITLE + " TEXT, " +
|
||||
MEMBERS + " TEXT, " +
|
||||
AVATAR_ID + " INTEGER, " +
|
||||
AVATAR_KEY + " BLOB, " +
|
||||
AVATAR_CONTENT_TYPE + " TEXT, " +
|
||||
AVATAR_RELAY + " TEXT, " +
|
||||
TIMESTAMP + " INTEGER, " +
|
||||
ACTIVE + " INTEGER DEFAULT 1, " +
|
||||
AVATAR_DIGEST + " BLOB, " +
|
||||
MMS + " INTEGER DEFAULT 0, " +
|
||||
V2_MASTER_KEY + " BLOB, " +
|
||||
V2_REVISION + " BLOB, " +
|
||||
V2_DECRYPTED_GROUP + " BLOB, " +
|
||||
EXPECTED_V2_ID + " TEXT DEFAULT NULL, " +
|
||||
UNMIGRATED_V1_MEMBERS + " TEXT DEFAULT NULL);";
|
||||
|
||||
public static final String[] CREATE_INDEXS = {
|
||||
"CREATE UNIQUE INDEX IF NOT EXISTS group_id_index ON " + TABLE_NAME + " (" + GROUP_ID + ");",
|
||||
@@ -106,7 +110,7 @@ public final class GroupDatabase extends Database {
|
||||
};
|
||||
|
||||
private static final String[] GROUP_PROJECTION = {
|
||||
GROUP_ID, RECIPIENT_ID, TITLE, MEMBERS, FORMER_V1_MEMBERS, AVATAR_ID, AVATAR_KEY, AVATAR_CONTENT_TYPE, AVATAR_RELAY, AVATAR_DIGEST,
|
||||
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
|
||||
};
|
||||
|
||||
@@ -162,9 +166,23 @@ public final class GroupDatabase extends Database {
|
||||
}
|
||||
}
|
||||
|
||||
public void clearFormerV1Members(@NonNull GroupId.V2 id) {
|
||||
/**
|
||||
* Removes the specified members from the list of 'unmigrated V1 members' -- the list of members
|
||||
* that were either dropped or had to be invited when migrating the group from V1->V2.
|
||||
*/
|
||||
public void removeUnmigratedV1Members(@NonNull GroupId.V2 id, @NonNull List<RecipientId> toRemove) {
|
||||
Optional<GroupRecord> group = getGroup(id);
|
||||
|
||||
if (!group.isPresent()) {
|
||||
Log.w(TAG, "Couldn't find the group!", new Throwable());
|
||||
return;
|
||||
}
|
||||
|
||||
List<RecipientId> newUnmigrated = group.get().getUnmigratedV1Members();
|
||||
newUnmigrated.removeAll(toRemove);
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.putNull(FORMER_V1_MEMBERS);
|
||||
values.put(UNMIGRATED_V1_MEMBERS, newUnmigrated.isEmpty() ? null : RecipientId.toSerializedList(newUnmigrated));
|
||||
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, values, GROUP_ID + " = ?", SqlUtil.buildArgs(id));
|
||||
|
||||
@@ -505,16 +523,15 @@ public final class GroupDatabase extends Database {
|
||||
contentValues.put(V2_MASTER_KEY, groupMasterKey.serialize());
|
||||
contentValues.putNull(EXPECTED_V2_ID);
|
||||
|
||||
List<RecipientId> newMembers = Stream.of(DecryptedGroupUtil.membersToUuidList(decryptedGroup.getMembersList())).map(u -> RecipientId.from(u, null)).toList();
|
||||
List<RecipientId> pendingMembers = Stream.of(DecryptedGroupUtil.pendingToUuidList(decryptedGroup.getPendingMembersList())).map(u -> RecipientId.from(u, null)).toList();
|
||||
List<RecipientId> newMembers = uuidsToRecipientIds(DecryptedGroupUtil.membersToUuidList(decryptedGroup.getMembersList()));
|
||||
List<RecipientId> pendingMembers = uuidsToRecipientIds(DecryptedGroupUtil.pendingToUuidList(decryptedGroup.getPendingMembersList()));
|
||||
|
||||
newMembers.addAll(pendingMembers);
|
||||
|
||||
List<RecipientId> droppedMembers = new ArrayList<>(SetUtil.difference(record.getMembers(), newMembers));
|
||||
List<RecipientId> droppedMembers = new ArrayList<>(SetUtil.difference(record.getMembers(), newMembers));
|
||||
List<RecipientId> unmigratedMembers = Util.concatenatedList(pendingMembers, droppedMembers);
|
||||
|
||||
if (droppedMembers.size() > 0) {
|
||||
contentValues.put(FORMER_V1_MEMBERS, RecipientId.toSerializedList(record.getMembers()));
|
||||
}
|
||||
contentValues.put(UNMIGRATED_V1_MEMBERS, unmigratedMembers.isEmpty() ? null : RecipientId.toSerializedList(unmigratedMembers));
|
||||
|
||||
int updated = db.update(TABLE_NAME, contentValues, GROUP_ID + " = ?", SqlUtil.buildArgs(groupIdV1.toString()));
|
||||
|
||||
@@ -543,10 +560,31 @@ public final class GroupDatabase extends Database {
|
||||
}
|
||||
|
||||
public void update(@NonNull GroupId.V2 groupId, @NonNull DecryptedGroup decryptedGroup) {
|
||||
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
|
||||
RecipientId groupRecipientId = recipientDatabase.getOrInsertFromGroupId(groupId);
|
||||
String title = decryptedGroup.getTitle();
|
||||
ContentValues contentValues = new ContentValues();
|
||||
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
|
||||
RecipientId groupRecipientId = recipientDatabase.getOrInsertFromGroupId(groupId);
|
||||
Optional<GroupRecord> existingGroup = getGroup(groupId);
|
||||
String title = decryptedGroup.getTitle();
|
||||
ContentValues contentValues = new ContentValues();
|
||||
|
||||
if (existingGroup.isPresent() && existingGroup.get().getUnmigratedV1Members().size() > 0 && existingGroup.get().isV2Group()) {
|
||||
Set<RecipientId> unmigratedV1Members = new HashSet<>(existingGroup.get().getUnmigratedV1Members());
|
||||
|
||||
DecryptedGroupChange change = GroupChangeReconstruct.reconstructGroupChange(existingGroup.get().requireV2GroupProperties().getDecryptedGroup(), decryptedGroup);
|
||||
|
||||
List<RecipientId> addedMembers = uuidsToRecipientIds(DecryptedGroupUtil.membersToUuidList(change.getNewMembersList()));
|
||||
List<RecipientId> removedMembers = uuidsToRecipientIds(DecryptedGroupUtil.removedMembersUuidList(change));
|
||||
List<RecipientId> addedInvites = uuidsToRecipientIds(DecryptedGroupUtil.pendingToUuidList(change.getNewPendingMembersList()));
|
||||
List<RecipientId> removedInvites = uuidsToRecipientIds(DecryptedGroupUtil.removedPendingMembersUuidList(change));
|
||||
List<RecipientId> acceptedInvites = uuidsToRecipientIds(DecryptedGroupUtil.membersToUuidList(change.getPromotePendingMembersList()));
|
||||
|
||||
unmigratedV1Members.removeAll(addedMembers);
|
||||
unmigratedV1Members.removeAll(removedMembers);
|
||||
unmigratedV1Members.removeAll(addedInvites);
|
||||
unmigratedV1Members.removeAll(removedInvites);
|
||||
unmigratedV1Members.removeAll(acceptedInvites);
|
||||
|
||||
contentValues.put(UNMIGRATED_V1_MEMBERS, unmigratedV1Members.isEmpty() ? null : RecipientId.toSerializedList(unmigratedV1Members));
|
||||
}
|
||||
|
||||
contentValues.put(TITLE, title);
|
||||
contentValues.put(V2_REVISION, decryptedGroup.getRevision());
|
||||
@@ -688,16 +726,11 @@ public final class GroupDatabase extends Database {
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public boolean isPendingMember(@NonNull GroupId.Push groupId, @NonNull Recipient recipient) {
|
||||
return getGroup(groupId).transform(g -> g.isPendingMember(recipient)).or(false);
|
||||
}
|
||||
|
||||
private static String serializeV2GroupMembers(@NonNull DecryptedGroup decryptedGroup) {
|
||||
List<RecipientId> groupMembers = new ArrayList<>(decryptedGroup.getMembersCount());
|
||||
private static List<RecipientId> uuidsToRecipientIds(@NonNull List<UUID> uuids) {
|
||||
List<RecipientId> groupMembers = new ArrayList<>(uuids.size());
|
||||
|
||||
for (DecryptedMember member : decryptedGroup.getMembersList()) {
|
||||
UUID uuid = UuidUtil.fromByteString(member.getUuid());
|
||||
for (UUID uuid : uuids) {
|
||||
if (UuidUtil.UNKNOWN_UUID.equals(uuid)) {
|
||||
Log.w(TAG, "Seen unknown UUID in members list");
|
||||
} else {
|
||||
@@ -707,7 +740,14 @@ public final class GroupDatabase extends Database {
|
||||
|
||||
Collections.sort(groupMembers);
|
||||
|
||||
return RecipientId.toSerializedList(groupMembers);
|
||||
return groupMembers;
|
||||
}
|
||||
|
||||
private static String serializeV2GroupMembers(@NonNull DecryptedGroup decryptedGroup) {
|
||||
List<UUID> uuids = DecryptedGroupUtil.membersToUuidList(decryptedGroup.getMembersList());
|
||||
List<RecipientId> recipientIds = uuidsToRecipientIds(uuids);
|
||||
|
||||
return RecipientId.toSerializedList(recipientIds);
|
||||
}
|
||||
|
||||
public @NonNull List<GroupId.V2> getAllGroupV2Ids() {
|
||||
@@ -772,7 +812,7 @@ public final class GroupDatabase extends Database {
|
||||
RecipientId.from(CursorUtil.requireString(cursor, RECIPIENT_ID)),
|
||||
CursorUtil.requireString(cursor, TITLE),
|
||||
CursorUtil.requireString(cursor, MEMBERS),
|
||||
CursorUtil.requireString(cursor, FORMER_V1_MEMBERS),
|
||||
CursorUtil.requireString(cursor, UNMIGRATED_V1_MEMBERS),
|
||||
CursorUtil.requireLong(cursor, AVATAR_ID),
|
||||
CursorUtil.requireBlob(cursor, AVATAR_KEY),
|
||||
CursorUtil.requireString(cursor, AVATAR_CONTENT_TYPE),
|
||||
@@ -798,7 +838,7 @@ public final class GroupDatabase extends Database {
|
||||
private final RecipientId recipientId;
|
||||
private final String title;
|
||||
private final List<RecipientId> members;
|
||||
private final List<RecipientId> formerV1Members;
|
||||
private final List<RecipientId> unmigratedV1Members;
|
||||
private final long avatarId;
|
||||
private final byte[] avatarKey;
|
||||
private final byte[] avatarDigest;
|
||||
@@ -812,7 +852,7 @@ public final class GroupDatabase extends Database {
|
||||
@NonNull RecipientId recipientId,
|
||||
String title,
|
||||
String members,
|
||||
String formerV1Members,
|
||||
@Nullable String unmigratedV1Members,
|
||||
long avatarId,
|
||||
byte[] avatarKey,
|
||||
String avatarContentType,
|
||||
@@ -853,10 +893,10 @@ public final class GroupDatabase extends Database {
|
||||
this.members = Collections.emptyList();
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(formerV1Members)) {
|
||||
this.formerV1Members = RecipientId.fromSerializedList(formerV1Members);
|
||||
if (!TextUtils.isEmpty(unmigratedV1Members)) {
|
||||
this.unmigratedV1Members = RecipientId.fromSerializedList(unmigratedV1Members);
|
||||
} else {
|
||||
this.formerV1Members = Collections.emptyList();
|
||||
this.unmigratedV1Members = Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -876,8 +916,9 @@ public final class GroupDatabase extends Database {
|
||||
return members;
|
||||
}
|
||||
|
||||
public @NonNull List<RecipientId> getFormerV1Members() {
|
||||
return formerV1Members;
|
||||
/** V1 members that were lost during the V1->V2 migration */
|
||||
public @NonNull List<RecipientId> getUnmigratedV1Members() {
|
||||
return unmigratedV1Members;
|
||||
}
|
||||
|
||||
public boolean hasAvatar() {
|
||||
|
@@ -164,8 +164,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
private static final int GV1_MIGRATION_LAST_SEEN = 82;
|
||||
private static final int VIEWED_RECEIPTS = 83;
|
||||
private static final int CLEAN_UP_GV1_IDS = 84;
|
||||
private static final int GV1_MIGRATION_REFACTOR = 85;
|
||||
|
||||
private static final int DATABASE_VERSION = 84;
|
||||
private static final int DATABASE_VERSION = 85;
|
||||
private static final String DATABASE_NAME = "signal.db";
|
||||
|
||||
private final Context context;
|
||||
@@ -1234,6 +1235,15 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
}
|
||||
}
|
||||
|
||||
if (oldVersion < GV1_MIGRATION_REFACTOR) {
|
||||
ContentValues values = new ContentValues(1);
|
||||
values.putNull("former_v1_members");
|
||||
|
||||
int count = db.update("groups", values, "former_v1_members NOT NULL", null);
|
||||
|
||||
Log.i(TAG, "Cleared former_v1_members for " + count + " rows");
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
|
@@ -75,15 +75,15 @@ public final class GroupsV1MigrationSuggestionsDialog {
|
||||
SimpleTask.run(SignalExecutors.UNBOUNDED, () -> {
|
||||
try {
|
||||
GroupManager.addMembers(fragmentActivity, groupId.requirePush(), suggestions);
|
||||
Log.i(TAG, "Successfully added members! Clearing former members.");
|
||||
DatabaseFactory.getGroupDatabase(fragmentActivity).clearFormerV1Members(groupId);
|
||||
Log.i(TAG, "Successfully added members! Removing these dropped members from the list.");
|
||||
DatabaseFactory.getGroupDatabase(fragmentActivity).removeUnmigratedV1Members(groupId, suggestions);
|
||||
return Result.SUCCESS;
|
||||
} catch (IOException | GroupChangeBusyException e) {
|
||||
Log.w(TAG, "Temporary failure.", e);
|
||||
return Result.NETWORK_ERROR;
|
||||
} catch (GroupNotAMemberException | GroupInsufficientRightsException | MembershipNotSuitableForV2Exception | GroupChangeFailedException e) {
|
||||
Log.w(TAG, "Permanent failure! Clearing former members.", e);
|
||||
DatabaseFactory.getGroupDatabase(fragmentActivity).clearFormerV1Members(groupId);
|
||||
Log.w(TAG, "Permanent failure! Removing these dropped members from the list.", e);
|
||||
DatabaseFactory.getGroupDatabase(fragmentActivity).removeUnmigratedV1Members(groupId, suggestions);
|
||||
return Result.IMPOSSIBLE;
|
||||
}
|
||||
}, result -> {
|
||||
|
@@ -17,6 +17,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -94,7 +95,7 @@ public class RecipientId implements Parcelable, Comparable<RecipientId> {
|
||||
id = in.readLong();
|
||||
}
|
||||
|
||||
public static @NonNull String toSerializedList(@NonNull List<RecipientId> ids) {
|
||||
public static @NonNull String toSerializedList(@NonNull Collection<RecipientId> ids) {
|
||||
return Util.join(Stream.of(ids).map(RecipientId::serialize).toList(), String.valueOf(DELIMITER));
|
||||
}
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<item name="reminder_action_update_now" type="id" />
|
||||
<item name="reminder_action_review_join_requests" type="id" />
|
||||
|
||||
<item name="reminder_action_gv1_suggestion_not_now" type="id" />
|
||||
<item name="reminder_action_gv1_suggestion_no_thanks" type="id" />
|
||||
<item name="reminder_action_gv1_suggestion_add_members" type="id" />
|
||||
|
||||
<item name="reminder_action_gv1_initiation_not_now" type="id" />
|
||||
|
@@ -613,7 +613,7 @@
|
||||
<item quantity="one">Add member</item>
|
||||
<item quantity="other">Add members</item>
|
||||
</plurals>
|
||||
<string name="GroupsV1MigrationSuggestionsReminder_not_now">Not now</string>
|
||||
<string name="GroupsV1MigrationSuggestionsReminder_no_thanks">No thanks</string>
|
||||
|
||||
<!-- GroupsV1MigrationSuggestionsDialog -->
|
||||
<plurals name="GroupsV1MigrationSuggestionsDialog_add_members_question">
|
||||
|
Reference in New Issue
Block a user