mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-07-13 17:23:56 +01:00
Convert GroupTable to kotlin.
Also required converting some tests to mockk.
This commit is contained in:
+4
-4
@@ -11,9 +11,9 @@ import org.signal.core.util.logging.Log
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember
|
||||
import org.thoughtcrime.securesms.contacts.sync.ContactDiscovery
|
||||
import org.thoughtcrime.securesms.database.GroupTable
|
||||
import org.thoughtcrime.securesms.database.MediaTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord
|
||||
import org.thoughtcrime.securesms.database.model.IdentityRecord
|
||||
import org.thoughtcrime.securesms.database.model.StoryViewState
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
@@ -70,7 +70,7 @@ class ConversationSettingsRepository(
|
||||
fun isInternalRecipientDetailsEnabled(): Boolean = SignalStore.internalValues().recipientDetails()
|
||||
|
||||
fun hasGroups(consumer: (Boolean) -> Unit) {
|
||||
SignalExecutors.BOUNDED.execute { consumer(SignalDatabase.groups.activeGroupCount > 0) }
|
||||
SignalExecutors.BOUNDED.execute { consumer(SignalDatabase.groups.getActiveGroupCount() > 0) }
|
||||
}
|
||||
|
||||
fun getIdentity(recipientId: RecipientId, consumer: (IdentityRecord?) -> Unit) {
|
||||
@@ -91,7 +91,7 @@ class ConversationSettingsRepository(
|
||||
.getPushGroupsContainingMember(recipientId)
|
||||
.asSequence()
|
||||
.filter { it.members.contains(Recipient.self().id) }
|
||||
.map(GroupTable.GroupRecord::getRecipientId)
|
||||
.map(GroupRecord::recipientId)
|
||||
.map(Recipient::resolved)
|
||||
.sortedBy { gr -> gr.getDisplayName(context) }
|
||||
.toList()
|
||||
@@ -129,7 +129,7 @@ class ConversationSettingsRepository(
|
||||
|
||||
fun getGroupCapacity(groupId: GroupId, consumer: (GroupCapacityResult) -> Unit) {
|
||||
SignalExecutors.BOUNDED.execute {
|
||||
val groupRecord: GroupTable.GroupRecord = SignalDatabase.groups.getGroup(groupId).get()
|
||||
val groupRecord: GroupRecord = SignalDatabase.groups.getGroup(groupId).get()
|
||||
consumer(
|
||||
if (groupRecord.isV2Group) {
|
||||
val decryptedGroup: DecryptedGroup = groupRecord.requireV2GroupProperties().decryptedGroup
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.RecipientTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadTable;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
import org.thoughtcrime.securesms.phonenumbers.NumberUtil;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
@@ -221,11 +222,11 @@ public class ContactsCursorLoader extends AbstractContactsCursorLoader {
|
||||
}
|
||||
|
||||
private Cursor getGroupsCursor() {
|
||||
MatrixCursor groupContacts = ContactsCursorRows.createMatrixCursor();
|
||||
Map<RecipientId, GroupTable.GroupRecord> groups = new LinkedHashMap<>();
|
||||
MatrixCursor groupContacts = ContactsCursorRows.createMatrixCursor();
|
||||
Map<RecipientId, GroupRecord> groups = new LinkedHashMap<>();
|
||||
|
||||
try (GroupTable.Reader reader = SignalDatabase.groups().queryGroupsByTitle(getFilter(), flagSet(mode, DisplayMode.FLAG_INACTIVE_GROUPS), hideGroupsV1(mode), !smsEnabled(mode))) {
|
||||
GroupTable.GroupRecord groupRecord;
|
||||
GroupRecord groupRecord;
|
||||
while ((groupRecord = reader.getNext()) != null) {
|
||||
groups.put(groupRecord.getRecipientId(), groupRecord);
|
||||
}
|
||||
@@ -240,14 +241,14 @@ public class ContactsCursorLoader extends AbstractContactsCursorLoader {
|
||||
}
|
||||
|
||||
try (GroupTable.Reader reader = SignalDatabase.groups().queryGroupsByMembership(filteredContacts, flagSet(mode, DisplayMode.FLAG_INACTIVE_GROUPS), hideGroupsV1(mode), !smsEnabled(mode))) {
|
||||
GroupTable.GroupRecord groupRecord;
|
||||
GroupRecord groupRecord;
|
||||
while ((groupRecord = reader.getNext()) != null) {
|
||||
groups.put(groupRecord.getRecipientId(), groupRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (GroupTable.GroupRecord groupRecord : groups.values()) {
|
||||
for (GroupRecord groupRecord : groups.values()) {
|
||||
groupContacts.addRow(ContactsCursorRows.forGroup(groupRecord));
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import android.provider.ContactsContract;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.whispersystems.signalservice.api.util.OptionalUtil;
|
||||
@@ -74,7 +74,7 @@ public final class ContactsCursorRows {
|
||||
/**
|
||||
* Create a row for a contacts cursor based off the given group record.
|
||||
*/
|
||||
public static @NonNull Object[] forGroup(@NonNull GroupTable.GroupRecord groupRecord) {
|
||||
public static @NonNull Object[] forGroup(@NonNull GroupRecord groupRecord) {
|
||||
return new Object[]{groupRecord.getRecipientId().serialize(),
|
||||
groupRecord.getTitle(),
|
||||
groupRecord.getId(),
|
||||
|
||||
+3
-2
@@ -10,6 +10,7 @@ import androidx.annotation.Nullable;
|
||||
import org.signal.core.util.Conversions;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||
|
||||
@@ -30,8 +31,8 @@ public final class GroupRecordContactPhoto implements ContactPhoto {
|
||||
|
||||
@Override
|
||||
public InputStream openInputStream(Context context) throws IOException {
|
||||
GroupTable groupDatabase = SignalDatabase.groups();
|
||||
Optional<GroupTable.GroupRecord> groupRecord = groupDatabase.getGroup(groupId);
|
||||
GroupTable groupDatabase = SignalDatabase.groups();
|
||||
Optional<GroupRecord> groupRecord = groupDatabase.getGroup(groupId);
|
||||
|
||||
if (!groupRecord.isPresent() || !AvatarHelper.hasAvatar(context, groupRecord.get().getRecipientId())) {
|
||||
throw new IOException("No avatar for group: " + groupId);
|
||||
|
||||
+1
-1
@@ -6,8 +6,8 @@ import org.thoughtcrime.securesms.contacts.paged.collections.ContactSearchCollec
|
||||
import org.thoughtcrime.securesms.contacts.paged.collections.ContactSearchIterator
|
||||
import org.thoughtcrime.securesms.contacts.paged.collections.CursorSearchIterator
|
||||
import org.thoughtcrime.securesms.contacts.paged.collections.StoriesSearchCollection
|
||||
import org.thoughtcrime.securesms.database.GroupTable.GroupRecord
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListPrivacyMode
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.keyvalue.StorySend
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
+2
-2
@@ -8,10 +8,10 @@ import org.thoughtcrime.securesms.contacts.ContactRepository
|
||||
import org.thoughtcrime.securesms.contacts.paged.collections.ContactSearchIterator
|
||||
import org.thoughtcrime.securesms.database.DistributionListTables
|
||||
import org.thoughtcrime.securesms.database.GroupTable
|
||||
import org.thoughtcrime.securesms.database.GroupTable.GroupRecord
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.ThreadTable
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListPrivacyMode
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.keyvalue.StorySend
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
@@ -104,7 +104,7 @@ open class ContactSearchPagedDataSourceRepository(
|
||||
}
|
||||
|
||||
open fun getGroupStories(): Set<ContactSearchData.Story> {
|
||||
return SignalDatabase.groups.groupsToDisplayAsStories.map {
|
||||
return SignalDatabase.groups.getGroupsToDisplayAsStories().map {
|
||||
val recipient = Recipient.resolved(SignalDatabase.recipients.getOrInsertFromGroupId(it))
|
||||
ContactSearchData.Story(recipient, recipient.participantIds.size, DistributionListPrivacyMode.ALL)
|
||||
}.toSet()
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ import com.annimon.stream.Stream;
|
||||
|
||||
import org.signal.core.util.concurrent.SignalExecutors;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.GroupTable.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupChangeBusyException;
|
||||
|
||||
+2
-1
@@ -328,7 +328,8 @@ import io.reactivex.rxjava3.core.Flowable;
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
|
||||
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
|
||||
import static org.thoughtcrime.securesms.database.GroupTable.GroupRecord;
|
||||
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
|
||||
/**
|
||||
* Fragment for displaying a message thread, as well as
|
||||
|
||||
+2
-2
@@ -10,11 +10,11 @@ import org.signal.core.util.concurrent.SignalExecutors;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.contacts.sync.ContactDiscovery;
|
||||
import org.thoughtcrime.securesms.database.DatabaseObserver;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.MessageTable;
|
||||
import org.thoughtcrime.securesms.database.RecipientTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadTable;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceViewedUpdateJob;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
@@ -84,7 +84,7 @@ class ConversationRepository {
|
||||
boolean isGroup = false;
|
||||
boolean recipientIsKnownOrHasGroupsInCommon = false;
|
||||
if (conversationRecipient.isGroup()) {
|
||||
Optional<GroupTable.GroupRecord> group = SignalDatabase.groups().getGroup(conversationRecipient.getId());
|
||||
Optional<GroupRecord> group = SignalDatabase.groups().getGroup(conversationRecipient.getId());
|
||||
if (group.isPresent()) {
|
||||
List<Recipient> recipients = Recipient.resolvedList(group.get().getMembers());
|
||||
for (Recipient recipient : recipients) {
|
||||
|
||||
+2
-2
@@ -15,8 +15,8 @@ import androidx.fragment.app.FragmentManager;
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.groups.ParcelableGroupId;
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupMemberListView;
|
||||
@@ -94,7 +94,7 @@ public final class ShowAdminsBottomSheetDialog extends BottomSheetDialogFragment
|
||||
private static @NonNull List<Recipient> getAdmins(@NonNull Context context, @NonNull GroupId groupId) {
|
||||
return SignalDatabase.groups()
|
||||
.getGroup(groupId)
|
||||
.map(GroupTable.GroupRecord::getAdmins)
|
||||
.map(GroupRecord::getAdmins)
|
||||
.orElse(Collections.emptyList());
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -54,6 +54,7 @@ import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||
import org.thoughtcrime.securesms.database.documents.NetworkFailureSet;
|
||||
import org.thoughtcrime.securesms.database.model.DisplayRecord;
|
||||
import org.thoughtcrime.securesms.database.model.GroupCallUpdateDetailsUtil;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.Mention;
|
||||
import org.thoughtcrime.securesms.database.model.MessageExportStatus;
|
||||
@@ -941,9 +942,9 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie
|
||||
}
|
||||
|
||||
public void insertProfileNameChangeMessages(@NonNull Recipient recipient, @NonNull String newProfileName, @NonNull String previousProfileName) {
|
||||
ThreadTable threadTable = SignalDatabase.threads();
|
||||
List<GroupTable.GroupRecord> groupRecords = SignalDatabase.groups().getGroupsContainingMember(recipient.getId(), false);
|
||||
List<Long> threadIdsToUpdate = new LinkedList<>();
|
||||
ThreadTable threadTable = SignalDatabase.threads();
|
||||
List<GroupRecord> groupRecords = SignalDatabase.groups().getGroupsContainingMember(recipient.getId(), false);
|
||||
List<Long> threadIdsToUpdate = new LinkedList<>();
|
||||
|
||||
byte[] profileChangeDetails = ProfileChangeDetails.newBuilder()
|
||||
.setProfileNameChange(ProfileChangeDetails.StringChange.newBuilder()
|
||||
@@ -959,7 +960,7 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie
|
||||
|
||||
try {
|
||||
threadIdsToUpdate.add(threadTable.getThreadIdFor(recipient.getId()));
|
||||
for (GroupTable.GroupRecord groupRecord : groupRecords) {
|
||||
for (GroupRecord groupRecord : groupRecords) {
|
||||
if (groupRecord.isActive()) {
|
||||
threadIdsToUpdate.add(threadTable.getThreadIdFor(groupRecord.getRecipientId()));
|
||||
}
|
||||
@@ -1032,16 +1033,16 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie
|
||||
}
|
||||
|
||||
public void insertNumberChangeMessages(@NonNull RecipientId recipientId) {
|
||||
ThreadTable threadTable = SignalDatabase.threads();
|
||||
List<GroupTable.GroupRecord> groupRecords = SignalDatabase.groups().getGroupsContainingMember(recipientId, false);
|
||||
List<Long> threadIdsToUpdate = new LinkedList<>();
|
||||
ThreadTable threadTable = SignalDatabase.threads();
|
||||
List<GroupRecord> groupRecords = SignalDatabase.groups().getGroupsContainingMember(recipientId, false);
|
||||
List<Long> threadIdsToUpdate = new LinkedList<>();
|
||||
|
||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||
db.beginTransaction();
|
||||
|
||||
try {
|
||||
threadIdsToUpdate.add(threadTable.getThreadIdFor(recipientId));
|
||||
for (GroupTable.GroupRecord groupRecord : groupRecords) {
|
||||
for (GroupRecord groupRecord : groupRecords) {
|
||||
if (groupRecord.isActive()) {
|
||||
threadIdsToUpdate.add(threadTable.getThreadIdFor(groupRecord.getRecipientId()));
|
||||
}
|
||||
|
||||
@@ -1186,7 +1186,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
}
|
||||
}
|
||||
|
||||
for (id in groups.allGroupV2Ids) {
|
||||
for (id in groups.getAllGroupV2Ids()) {
|
||||
val recipient = Recipient.externalGroupExact(id!!)
|
||||
val recipientId = recipient.id
|
||||
val existing: RecipientRecord = getRecordForSync(recipientId) ?: throw AssertionError()
|
||||
|
||||
@@ -1670,7 +1670,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
||||
val recipientSettings = recipients.getRecord(context, cursor, RECIPIENT_ID)
|
||||
|
||||
val recipient: Recipient = if (recipientSettings.groupId != null) {
|
||||
GroupTable.Reader(cursor).current?.let { group ->
|
||||
GroupTable.Reader(cursor).getCurrent()?.let { group ->
|
||||
val details = RecipientDetails(
|
||||
group.title,
|
||||
null,
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
package org.thoughtcrime.securesms.database.model
|
||||
|
||||
import androidx.annotation.WorkerThread
|
||||
import org.signal.libsignal.zkgroup.groups.GroupMasterKey
|
||||
import org.signal.storageservice.protos.groups.AccessControl
|
||||
import org.signal.storageservice.protos.groups.local.EnabledState
|
||||
import org.thoughtcrime.securesms.database.GroupTable
|
||||
import org.thoughtcrime.securesms.groups.GroupAccessControl
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil
|
||||
import org.whispersystems.signalservice.api.push.DistributionId
|
||||
import java.lang.AssertionError
|
||||
import java.util.Optional
|
||||
|
||||
class GroupRecord(
|
||||
val id: GroupId,
|
||||
val recipientId: RecipientId,
|
||||
val title: String?,
|
||||
serializedMembers: String?,
|
||||
serializedUnmigratedV1Members: String?,
|
||||
val avatarId: Long,
|
||||
val avatarKey: ByteArray?,
|
||||
val avatarContentType: String?,
|
||||
val relay: String?,
|
||||
val isActive: Boolean,
|
||||
val avatarDigest: ByteArray?,
|
||||
val isMms: Boolean,
|
||||
groupMasterKeyBytes: ByteArray?,
|
||||
groupRevision: Int,
|
||||
decryptedGroupBytes: ByteArray?,
|
||||
val distributionId: DistributionId?,
|
||||
val lastForceUpdateTimestamp: Long
|
||||
) {
|
||||
|
||||
val members: List<RecipientId> by lazy {
|
||||
if (serializedMembers.isNullOrEmpty()) {
|
||||
emptyList()
|
||||
} else {
|
||||
RecipientId.fromSerializedList(serializedMembers)
|
||||
}
|
||||
}
|
||||
|
||||
/** V1 members that were lost during the V1->V2 migration */
|
||||
val unmigratedV1Members: List<RecipientId> by lazy {
|
||||
if (serializedUnmigratedV1Members.isNullOrEmpty()) {
|
||||
emptyList()
|
||||
} else {
|
||||
RecipientId.fromSerializedList(serializedUnmigratedV1Members)
|
||||
}
|
||||
}
|
||||
|
||||
private val v2GroupProperties: GroupTable.V2GroupProperties? by lazy {
|
||||
if (groupMasterKeyBytes != null && decryptedGroupBytes != null) {
|
||||
val groupMasterKey = GroupMasterKey(groupMasterKeyBytes)
|
||||
GroupTable.V2GroupProperties(groupMasterKey, groupRevision, decryptedGroupBytes)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
val description: String
|
||||
get() = v2GroupProperties?.decryptedGroup?.description ?: ""
|
||||
|
||||
val isAnnouncementGroup: Boolean
|
||||
get() = v2GroupProperties?.decryptedGroup?.isAnnouncementGroup == EnabledState.ENABLED
|
||||
|
||||
val isV1Group: Boolean
|
||||
get() = !isMms && !isV2Group
|
||||
|
||||
val isV2Group: Boolean
|
||||
get() = v2GroupProperties != null
|
||||
|
||||
@get:WorkerThread
|
||||
val admins: List<Recipient>
|
||||
get() {
|
||||
return if (v2GroupProperties != null) {
|
||||
val resolved = members.map { Recipient.resolved(it) }
|
||||
v2GroupProperties!!.getAdmins(resolved)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
/** Who is allowed to add to the membership of this group. */
|
||||
val membershipAdditionAccessControl: GroupAccessControl
|
||||
get() {
|
||||
return if (isV2Group) {
|
||||
if (requireV2GroupProperties().decryptedGroup.accessControl.members == AccessControl.AccessRequired.MEMBER) {
|
||||
GroupAccessControl.ALL_MEMBERS
|
||||
} else {
|
||||
GroupAccessControl.ONLY_ADMINS
|
||||
}
|
||||
} else if (isV1Group) {
|
||||
GroupAccessControl.NO_ONE
|
||||
} else if (id.isV1) {
|
||||
GroupAccessControl.ALL_MEMBERS
|
||||
} else {
|
||||
GroupAccessControl.ONLY_ADMINS
|
||||
}
|
||||
}
|
||||
|
||||
/** Who is allowed to modify the attributes of this group, name/avatar/timer etc. */
|
||||
val attributesAccessControl: GroupAccessControl
|
||||
get() {
|
||||
return if (isV2Group) {
|
||||
if (requireV2GroupProperties().decryptedGroup.accessControl.attributes == AccessControl.AccessRequired.MEMBER) {
|
||||
GroupAccessControl.ALL_MEMBERS
|
||||
} else {
|
||||
GroupAccessControl.ONLY_ADMINS
|
||||
}
|
||||
} else if (isV1Group) {
|
||||
GroupAccessControl.NO_ONE
|
||||
} else {
|
||||
GroupAccessControl.ALL_MEMBERS
|
||||
}
|
||||
}
|
||||
|
||||
fun hasAvatar(): Boolean {
|
||||
return avatarId != 0L
|
||||
}
|
||||
|
||||
fun requireV2GroupProperties(): GroupTable.V2GroupProperties {
|
||||
return v2GroupProperties ?: throw AssertionError()
|
||||
}
|
||||
|
||||
fun isAdmin(recipient: Recipient): Boolean {
|
||||
return isV2Group && requireV2GroupProperties().isAdmin(recipient)
|
||||
}
|
||||
|
||||
fun memberLevel(recipient: Recipient): GroupTable.MemberLevel {
|
||||
return if (isV2Group) {
|
||||
val memberLevel = requireV2GroupProperties().memberLevel(recipient.serviceId)
|
||||
if (recipient.isSelf && memberLevel == GroupTable.MemberLevel.NOT_A_MEMBER) {
|
||||
requireV2GroupProperties().memberLevel(Optional.ofNullable(SignalStore.account().pni))
|
||||
} else {
|
||||
memberLevel
|
||||
}
|
||||
} else if (isMms && recipient.isSelf) {
|
||||
GroupTable.MemberLevel.FULL_MEMBER
|
||||
} else if (members.contains(recipient.id)) {
|
||||
GroupTable.MemberLevel.FULL_MEMBER
|
||||
} else {
|
||||
GroupTable.MemberLevel.NOT_A_MEMBER
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the recipient is a pending member.
|
||||
*/
|
||||
fun isPendingMember(recipient: Recipient): Boolean {
|
||||
if (isV2Group) {
|
||||
val serviceId = recipient.serviceId
|
||||
if (serviceId.isPresent) {
|
||||
return DecryptedGroupUtil.findPendingByUuid(requireV2GroupProperties().decryptedGroup.pendingMembersList, serviceId.get().uuid())
|
||||
.isPresent
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import org.signal.core.util.concurrent.SignalExecutors;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
@@ -78,7 +79,7 @@ class DeleteAccountRepository {
|
||||
|
||||
int groupsLeft = 0;
|
||||
try (GroupTable.Reader groups = SignalDatabase.groups().getGroups()) {
|
||||
GroupTable.GroupRecord groupRecord = groups.getNext();
|
||||
GroupRecord groupRecord = groups.getNext();
|
||||
onDeleteAccountEvent.accept(new DeleteAccountEvent.LeaveGroupsProgress(groups.getCount(), 0));
|
||||
Log.i(TAG, "deleteAccount: found " + groups.getCount() + " groups to leave.");
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroupJoinInfo;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupInviteLinkUrl;
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupLinkPassword;
|
||||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||
@@ -402,14 +403,14 @@ public final class GroupManager {
|
||||
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException, GroupChangeBusyException, MembershipNotSuitableForV2Exception
|
||||
{
|
||||
if (groupId.isV2()) {
|
||||
GroupTable.GroupRecord groupRecord = SignalDatabase.groups().requireGroup(groupId);
|
||||
GroupRecord groupRecord = SignalDatabase.groups().requireGroup(groupId);
|
||||
|
||||
try (GroupManagerV2.GroupEditor editor = new GroupManagerV2(context).edit(groupId.requireV2())) {
|
||||
return editor.addMembers(newMembers, groupRecord.requireV2GroupProperties().getBannedMembers());
|
||||
}
|
||||
} else {
|
||||
GroupTable.GroupRecord groupRecord = SignalDatabase.groups().requireGroup(groupId);
|
||||
List<RecipientId> members = groupRecord.getMembers();
|
||||
GroupRecord groupRecord = SignalDatabase.groups().requireGroup(groupId);
|
||||
List<RecipientId> members = groupRecord.getMembers();
|
||||
byte[] avatar = groupRecord.hasAvatar() ? AvatarHelper.getAvatarBytes(context, groupRecord.getRecipientId()) : null;
|
||||
Set<RecipientId> recipientIds = new HashSet<>(members);
|
||||
int originalSize = recipientIds.size();
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadTable;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupCandidateHelper;
|
||||
@@ -167,8 +168,8 @@ final class GroupManagerV2 {
|
||||
|
||||
@WorkerThread
|
||||
@NonNull Map<UUID, UuidCiphertext> getUuidCipherTexts(@NonNull GroupId.V2 groupId) {
|
||||
GroupTable.GroupRecord groupRecord = SignalDatabase.groups().requireGroup(groupId);
|
||||
GroupTable.V2GroupProperties v2GroupProperties = groupRecord.requireV2GroupProperties();
|
||||
GroupRecord groupRecord = SignalDatabase.groups().requireGroup(groupId);
|
||||
GroupTable.V2GroupProperties v2GroupProperties = groupRecord.requireV2GroupProperties();
|
||||
GroupMasterKey groupMasterKey = v2GroupProperties.getGroupMasterKey();
|
||||
ClientZkGroupCipher clientZkGroupCipher = new ClientZkGroupCipher(GroupSecretParams.deriveFromMasterKey(groupMasterKey));
|
||||
List<Recipient> recipients = v2GroupProperties.getMemberRecipients(GroupTable.MemberSet.FULL_MEMBERS_INCLUDING_SELF);
|
||||
@@ -251,9 +252,9 @@ final class GroupManagerV2 {
|
||||
throws IOException, MembershipNotSuitableForV2Exception, GroupAlreadyExistsException, GroupChangeFailedException
|
||||
{
|
||||
GroupMasterKey groupMasterKey = groupIdV1.deriveV2MigrationMasterKey();
|
||||
GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey);
|
||||
GroupTable.GroupRecord groupRecord = groupDatabase.requireGroup(groupIdV1);
|
||||
String name = Util.emptyIfNull(groupRecord.getTitle());
|
||||
GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey);
|
||||
GroupRecord groupRecord = groupDatabase.requireGroup(groupIdV1);
|
||||
String name = Util.emptyIfNull(groupRecord.getTitle());
|
||||
byte[] avatar = groupRecord.hasAvatar() ? AvatarHelper.getAvatarBytes(context, groupRecord.getRecipientId()) : null;
|
||||
int messageTimer = Recipient.resolved(groupRecord.getRecipientId()).getExpiresInSeconds();
|
||||
Set<RecipientId> memberIds = Stream.of(members)
|
||||
@@ -327,7 +328,7 @@ final class GroupManagerV2 {
|
||||
GroupEditor(@NonNull GroupId.V2 groupId, @NonNull Closeable lock) {
|
||||
super(lock);
|
||||
|
||||
GroupTable.GroupRecord groupRecord = groupDatabase.requireGroup(groupId);
|
||||
GroupRecord groupRecord = groupDatabase.requireGroup(groupId);
|
||||
|
||||
this.groupId = groupId;
|
||||
this.v2GroupProperties = groupRecord.requireV2GroupProperties();
|
||||
@@ -455,8 +456,8 @@ final class GroupManagerV2 {
|
||||
void leaveGroup()
|
||||
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
|
||||
{
|
||||
GroupTable.GroupRecord groupRecord = groupDatabase.requireGroup(groupId);
|
||||
DecryptedGroup decryptedGroup = groupRecord.requireV2GroupProperties().getDecryptedGroup();
|
||||
GroupRecord groupRecord = groupDatabase.requireGroup(groupId);
|
||||
DecryptedGroup decryptedGroup = groupRecord.requireV2GroupProperties().getDecryptedGroup();
|
||||
Optional<DecryptedMember> selfMember = DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), selfAci.uuid());
|
||||
Optional<DecryptedPendingMember> aciPendingMember = DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), selfAci.uuid());
|
||||
Optional<DecryptedPendingMember> pniPendingMember = DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), selfPni.uuid());
|
||||
@@ -728,7 +729,7 @@ final class GroupManagerV2 {
|
||||
private GroupManager.GroupActionResult commitChange(@NonNull GroupChange.Actions.Builder change, boolean allowWhenBlocked, boolean sendToMembers)
|
||||
throws GroupNotAMemberException, GroupChangeFailedException, IOException, GroupInsufficientRightsException
|
||||
{
|
||||
final GroupTable.GroupRecord groupRecord = groupDatabase.requireGroup(groupId);
|
||||
final GroupRecord groupRecord = groupDatabase.requireGroup(groupId);
|
||||
final GroupTable.V2GroupProperties v2GroupProperties = groupRecord.requireV2GroupProperties();
|
||||
final int nextRevision = v2GroupProperties.getGroupRevision() + 1;
|
||||
final GroupChange.Actions changeActions = change.setRevision(nextRevision).build();
|
||||
@@ -923,7 +924,7 @@ final class GroupManagerV2 {
|
||||
alreadyAMember = true;
|
||||
}
|
||||
|
||||
Optional<GroupTable.GroupRecord> unmigratedV1Group = groupDatabase.getGroupV1ByExpectedV2(groupId);
|
||||
Optional<GroupRecord> unmigratedV1Group = groupDatabase.getGroupV1ByExpectedV2(groupId);
|
||||
|
||||
if (unmigratedV1Group.isPresent()) {
|
||||
Log.i(TAG, "Group link was for a migrated V1 group we know about! Migrating it and using that as the base.");
|
||||
@@ -932,7 +933,7 @@ final class GroupManagerV2 {
|
||||
|
||||
DecryptedGroup decryptedGroup = createPlaceholderGroup(joinInfo, requestToJoin);
|
||||
|
||||
Optional<GroupTable.GroupRecord> group = groupDatabase.getGroup(groupId);
|
||||
Optional<GroupRecord> group = groupDatabase.getGroup(groupId);
|
||||
|
||||
if (group.isPresent()) {
|
||||
Log.i(TAG, "Group already present locally");
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupMemberEntry;
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupInviteLinkUrl;
|
||||
@@ -48,7 +49,7 @@ public final class LiveGroup {
|
||||
|
||||
private final GroupTable groupDatabase;
|
||||
private final LiveData<Recipient> recipient;
|
||||
private final LiveData<GroupTable.GroupRecord> groupRecord;
|
||||
private final LiveData<GroupRecord> groupRecord;
|
||||
private final LiveData<List<GroupMemberEntry.FullMember>> fullMembers;
|
||||
private final LiveData<List<GroupMemberEntry.RequestingMember>> requestingMembers;
|
||||
private final LiveData<GroupLinkUrlAndStatus> groupLink;
|
||||
@@ -64,7 +65,7 @@ public final class LiveGroup {
|
||||
this.requestingMembers = mapToRequestingMembers(this.groupRecord);
|
||||
|
||||
if (groupId.isV2()) {
|
||||
LiveData<GroupTable.V2GroupProperties> v2Properties = Transformations.map(this.groupRecord, GroupTable.GroupRecord::requireV2GroupProperties);
|
||||
LiveData<GroupTable.V2GroupProperties> v2Properties = Transformations.map(this.groupRecord, GroupRecord::requireV2GroupProperties);
|
||||
this.groupLink = Transformations.map(v2Properties, g -> {
|
||||
DecryptedGroup group = g.getDecryptedGroup();
|
||||
AccessControl.AccessRequired addFromInviteLink = group.getAccessControl().getAddFromInviteLink();
|
||||
@@ -87,7 +88,7 @@ public final class LiveGroup {
|
||||
SignalExecutors.BOUNDED.execute(() -> liveRecipient.postValue(Recipient.externalGroupExact(groupId).live()));
|
||||
}
|
||||
|
||||
protected static LiveData<List<GroupMemberEntry.FullMember>> mapToFullMembers(@NonNull LiveData<GroupTable.GroupRecord> groupRecord) {
|
||||
protected static LiveData<List<GroupMemberEntry.FullMember>> mapToFullMembers(@NonNull LiveData<GroupRecord> groupRecord) {
|
||||
return LiveDataUtil.mapAsync(groupRecord,
|
||||
g -> Stream.of(g.getMembers())
|
||||
.map(m -> {
|
||||
@@ -98,7 +99,7 @@ public final class LiveGroup {
|
||||
.toList());
|
||||
}
|
||||
|
||||
protected static LiveData<List<GroupMemberEntry.RequestingMember>> mapToRequestingMembers(@NonNull LiveData<GroupTable.GroupRecord> groupRecord) {
|
||||
protected static LiveData<List<GroupMemberEntry.RequestingMember>> mapToRequestingMembers(@NonNull LiveData<GroupRecord> groupRecord) {
|
||||
return LiveDataUtil.mapAsync(groupRecord,
|
||||
g -> {
|
||||
if (!g.isV2Group()) {
|
||||
@@ -128,11 +129,11 @@ public final class LiveGroup {
|
||||
}
|
||||
|
||||
public LiveData<String> getDescription() {
|
||||
return Transformations.map(groupRecord, GroupTable.GroupRecord::getDescription);
|
||||
return Transformations.map(groupRecord, GroupRecord::getDescription);
|
||||
}
|
||||
|
||||
public LiveData<Boolean> isAnnouncementGroup() {
|
||||
return Transformations.map(groupRecord, GroupTable.GroupRecord::isAnnouncementGroup);
|
||||
return Transformations.map(groupRecord, GroupRecord::isAnnouncementGroup);
|
||||
}
|
||||
|
||||
public LiveData<Recipient> getGroupRecipient() {
|
||||
@@ -148,7 +149,7 @@ public final class LiveGroup {
|
||||
}
|
||||
|
||||
public LiveData<Boolean> isActive() {
|
||||
return Transformations.map(groupRecord, GroupTable.GroupRecord::isActive);
|
||||
return Transformations.map(groupRecord, GroupRecord::isActive);
|
||||
}
|
||||
|
||||
public LiveData<Boolean> getRecipientIsAdmin(@NonNull RecipientId recipientId) {
|
||||
@@ -171,11 +172,11 @@ public final class LiveGroup {
|
||||
}
|
||||
|
||||
public LiveData<GroupAccessControl> getMembershipAdditionAccessControl() {
|
||||
return Transformations.map(groupRecord, GroupTable.GroupRecord::getMembershipAdditionAccessControl);
|
||||
return Transformations.map(groupRecord, GroupRecord::getMembershipAdditionAccessControl);
|
||||
}
|
||||
|
||||
public LiveData<GroupAccessControl> getAttributesAccessControl() {
|
||||
return Transformations.map(groupRecord, GroupTable.GroupRecord::getAttributesAccessControl);
|
||||
return Transformations.map(groupRecord, GroupRecord::getAttributesAccessControl);
|
||||
}
|
||||
|
||||
public LiveData<List<GroupMemberEntry.FullMember>> getNonAdminFullMembers() {
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.groups.GroupChangeException;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager;
|
||||
@@ -56,7 +57,7 @@ public final class LeaveGroupDialog {
|
||||
SimpleTask.run(activity.getLifecycle(), () -> {
|
||||
GroupTable.V2GroupProperties groupProperties = SignalDatabase.groups()
|
||||
.getGroup(groupId)
|
||||
.map(GroupTable.GroupRecord::requireV2GroupProperties)
|
||||
.map(GroupRecord::requireV2GroupProperties)
|
||||
.orElse(null);
|
||||
|
||||
if (groupProperties != null && groupProperties.isAdmin(Recipient.self())) {
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ import org.signal.storageservice.protos.groups.local.DecryptedMember;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.GroupTable.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.MessageTable;
|
||||
import org.thoughtcrime.securesms.database.RecipientTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.GroupTable.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
|
||||
@@ -5,7 +5,7 @@ import androidx.annotation.NonNull;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.libsignal.protocol.InvalidMessageException;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.GroupTable.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
|
||||
@@ -10,7 +10,7 @@ import org.signal.core.util.logging.Log;
|
||||
import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
|
||||
import org.signal.libsignal.zkgroup.groups.GroupSecretParams;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.GroupTable.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
|
||||
@@ -3,8 +3,8 @@ package org.thoughtcrime.securesms.jobs;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.signal.core.util.concurrent.SignalExecutors;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
@@ -28,7 +28,7 @@ public final class ForceUpdateGroupV2Job extends BaseJob {
|
||||
|
||||
public static void enqueueIfNecessary(@NonNull GroupId.V2 groupId) {
|
||||
SignalExecutors.BOUNDED.execute(() -> {
|
||||
Optional<GroupTable.GroupRecord> group = SignalDatabase.groups().getGroup(groupId);
|
||||
Optional<GroupRecord> group = SignalDatabase.groups().getGroup(groupId);
|
||||
if (group.isPresent() &&
|
||||
group.get().isV2Group() &&
|
||||
group.get().getLastForceUpdateTimestamp() + FORCE_UPDATE_INTERVAL < System.currentTimeMillis()
|
||||
|
||||
@@ -3,8 +3,8 @@ package org.thoughtcrime.securesms.jobs;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.groups.GroupChangeBusyException;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager;
|
||||
@@ -61,7 +61,7 @@ final class ForceUpdateGroupV2WorkerJob extends BaseJob {
|
||||
|
||||
@Override
|
||||
public void onRun() throws IOException, GroupNotAMemberException, GroupChangeBusyException {
|
||||
Optional<GroupTable.GroupRecord> group = SignalDatabase.groups().getGroup(groupId);
|
||||
Optional<GroupRecord> group = SignalDatabase.groups().getGroup(groupId);
|
||||
|
||||
if (!group.isPresent()) {
|
||||
Log.w(TAG, "Group not found");
|
||||
|
||||
+2
-2
@@ -8,8 +8,8 @@ import com.google.protobuf.ByteString;
|
||||
import org.signal.core.util.concurrent.SignalExecutors;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedMember;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupChangeBusyException;
|
||||
import org.thoughtcrime.securesms.groups.GroupChangeFailedException;
|
||||
@@ -112,7 +112,7 @@ public final class GroupV2UpdateSelfProfileKeyJob extends BaseJob {
|
||||
boolean foundMismatch = false;
|
||||
|
||||
for (GroupId.V2 id : SignalDatabase.groups().getAllGroupV2Ids()) {
|
||||
Optional<GroupTable.GroupRecord> group = SignalDatabase.groups().getGroup(id);
|
||||
Optional<GroupRecord> group = SignalDatabase.groups().getGroup(id);
|
||||
if (!group.isPresent()) {
|
||||
Log.w(TAG, "Group " + group + " no longer exists?");
|
||||
continue;
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.thoughtcrime.securesms.conversation.colors.ChatColorsMapper;
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
@@ -101,7 +102,7 @@ public class MultiDeviceGroupUpdateJob extends BaseJob {
|
||||
DeviceGroupsOutputStream out = new DeviceGroupsOutputStream(new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]));
|
||||
boolean hasData = false;
|
||||
|
||||
GroupTable.GroupRecord record;
|
||||
GroupRecord record;
|
||||
|
||||
while ((record = reader.getNext()) != null) {
|
||||
if (record.isV1Group()) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.thoughtcrime.securesms.database.RecipientTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MessageId;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
@@ -252,7 +253,7 @@ public final class PushGroupSendJob extends PushSendJob {
|
||||
.anyMatch(info -> info.getStatus() > GroupReceiptTable.STATUS_UNDELIVERED);
|
||||
|
||||
if (message.getStoryType().isStory()) {
|
||||
Optional<GroupTable.GroupRecord> groupRecord = SignalDatabase.groups().getGroup(groupId);
|
||||
Optional<GroupRecord> groupRecord = SignalDatabase.groups().getGroup(groupId);
|
||||
|
||||
if (groupRecord.isPresent() && groupRecord.get().isAnnouncementGroup() && !groupRecord.get().isAdmin(Recipient.self())) {
|
||||
throw new UndeliverableMessageException("Non-admins cannot send stories in announcement groups!");
|
||||
@@ -301,7 +302,7 @@ public final class PushGroupSendJob extends PushSendJob {
|
||||
throw new UndeliverableMessageException("Messages can no longer be sent to V1 groups!");
|
||||
}
|
||||
} else {
|
||||
Optional<GroupTable.GroupRecord> groupRecord = SignalDatabase.groups().getGroup(groupRecipient.requireGroupId());
|
||||
Optional<GroupRecord> groupRecord = SignalDatabase.groups().getGroup(groupRecipient.requireGroupId());
|
||||
|
||||
if (groupRecord.isPresent() && groupRecord.get().isAnnouncementGroup() && !groupRecord.get().isAdmin(Recipient.self())) {
|
||||
throw new UndeliverableMessageException("Non-admins cannot send messages in announcement groups!");
|
||||
|
||||
@@ -4,8 +4,8 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.groups.GroupChangeBusyException;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager;
|
||||
@@ -76,7 +76,7 @@ final class RequestGroupV2InfoWorkerJob extends BaseJob {
|
||||
Log.i(TAG, "Updating group to revision " + toRevision);
|
||||
}
|
||||
|
||||
Optional<GroupTable.GroupRecord> group = SignalDatabase.groups().getGroup(groupId);
|
||||
Optional<GroupRecord> group = SignalDatabase.groups().getGroup(groupId);
|
||||
|
||||
if (!group.isPresent()) {
|
||||
Log.w(TAG, "Group not found");
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.signal.core.util.logging.Log;
|
||||
import org.signal.libsignal.protocol.SignalProtocolAddress;
|
||||
import org.signal.libsignal.protocol.message.SenderKeyDistributionMessage;
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.database.GroupTable.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
|
||||
@@ -23,8 +23,8 @@ import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.attachments.UriAttachment;
|
||||
import org.thoughtcrime.securesms.database.AttachmentTable;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager;
|
||||
@@ -282,14 +282,14 @@ public class LinkPreviewRepository {
|
||||
}
|
||||
|
||||
GroupMasterKey groupMasterKey = groupInviteLinkUrl.getGroupMasterKey();
|
||||
GroupId.V2 groupId = GroupId.v2(groupMasterKey);
|
||||
Optional<GroupTable.GroupRecord> group = SignalDatabase.groups().getGroup(groupId);
|
||||
GroupId.V2 groupId = GroupId.v2(groupMasterKey);
|
||||
Optional<GroupRecord> group = SignalDatabase.groups().getGroup(groupId);
|
||||
|
||||
if (group.isPresent()) {
|
||||
Log.i(TAG, "Creating preview for locally available group");
|
||||
|
||||
GroupTable.GroupRecord groupRecord = group.get();
|
||||
String title = groupRecord.getTitle();
|
||||
GroupRecord groupRecord = group.get();
|
||||
String title = groupRecord.getTitle();
|
||||
int memberCount = groupRecord.getMembers().size();
|
||||
String description = getMemberCountDescription(context, memberCount);
|
||||
Optional<Attachment> thumbnail = Optional.empty();
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@ import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.RecipientTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadTable;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
@@ -121,7 +122,7 @@ class CameraContactsRepository {
|
||||
List<Recipient> recipients = new ArrayList<>();
|
||||
|
||||
try (GroupTable.Reader reader = groupDatabase.queryGroupsByTitle(query, false, true, true)) {
|
||||
GroupTable.GroupRecord groupRecord;
|
||||
GroupRecord groupRecord;
|
||||
while ((groupRecord = reader.getNext()) != null) {
|
||||
RecipientId recipientId = recipientTable.getOrInsertFromGroupId(groupRecord.getId());
|
||||
recipients.add(Recipient.resolved(recipientId));
|
||||
|
||||
+3
-2
@@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.database.MessageTable;
|
||||
import org.thoughtcrime.securesms.database.RecipientTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadTable;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupChangeException;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager;
|
||||
@@ -58,8 +59,8 @@ final class MessageRequestRepository {
|
||||
|
||||
void getGroupInfo(@NonNull RecipientId recipientId, @NonNull Consumer<GroupInfo> onGroupInfoLoaded) {
|
||||
executor.execute(() -> {
|
||||
GroupTable groupDatabase = SignalDatabase.groups();
|
||||
Optional<GroupTable.GroupRecord> groupRecord = groupDatabase.getGroup(recipientId);
|
||||
GroupTable groupDatabase = SignalDatabase.groups();
|
||||
Optional<GroupRecord> groupRecord = groupDatabase.getGroup(recipientId);
|
||||
onGroupInfoLoaded.accept(groupRecord.map(record -> {
|
||||
if (record.isV2Group()) {
|
||||
DecryptedGroup decryptedGroup = record.requireV2GroupProperties().getDecryptedGroup();
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.signal.libsignal.protocol.InvalidRegistrationIdException;
|
||||
import org.signal.libsignal.protocol.NoSessionException;
|
||||
import org.thoughtcrime.securesms.crypto.SenderKeyUtil;
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.database.GroupTable.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.MessageSendLogTables;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListId;
|
||||
|
||||
@@ -35,7 +35,7 @@ import org.thoughtcrime.securesms.crypto.SecurityEvent;
|
||||
import org.thoughtcrime.securesms.database.AttachmentTable;
|
||||
import org.thoughtcrime.securesms.database.CallTable;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.GroupTable.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.GroupReceiptTable;
|
||||
import org.thoughtcrime.securesms.database.GroupReceiptTable.GroupReceiptInfo;
|
||||
import org.thoughtcrime.securesms.database.MessageTable;
|
||||
|
||||
+2
-2
@@ -18,9 +18,9 @@ import androidx.core.graphics.drawable.IconCompat
|
||||
import org.signal.core.util.PendingIntentFlags.mutable
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.conversation.ConversationIntents
|
||||
import org.thoughtcrime.securesms.database.GroupTable
|
||||
import org.thoughtcrime.securesms.database.RecipientTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels
|
||||
import org.thoughtcrime.securesms.notifications.ReplyMethod
|
||||
@@ -117,7 +117,7 @@ sealed class NotificationBuilder(protected val context: Context) {
|
||||
fun addReplyActions(conversation: NotificationConversation) {
|
||||
if (privacy.isDisplayMessage && isNotLocked && !conversation.recipient.isPushV1Group && RecipientUtil.isMessageRequestAccepted(context, conversation.recipient)) {
|
||||
if (conversation.recipient.isPushV2Group) {
|
||||
val group: Optional<GroupTable.GroupRecord> = SignalDatabase.groups.getGroup(conversation.recipient.requireGroupId())
|
||||
val group: Optional<GroupRecord> = SignalDatabase.groups.getGroup(conversation.recipient.requireGroupId())
|
||||
if (group.isPresent && group.get().isAnnouncementGroup && !group.get().isAdmin(Recipient.self())) {
|
||||
return
|
||||
}
|
||||
|
||||
+2
-2
@@ -10,8 +10,8 @@ import androidx.core.util.Consumer;
|
||||
import org.signal.core.util.StreamUtil;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColor;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.groups.GroupChangeException;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager;
|
||||
@@ -92,7 +92,7 @@ class EditGroupProfileRepository implements EditProfileRepository {
|
||||
|
||||
return SignalDatabase.groups()
|
||||
.getGroup(recipientId)
|
||||
.map(GroupTable.GroupRecord::getDescription)
|
||||
.map(GroupRecord::getDescription)
|
||||
.orElse("");
|
||||
}, descriptionConsumer::accept);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.annimon.stream.Stream;
|
||||
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ProfileChangeDetails;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
@@ -105,7 +106,7 @@ public final class ReviewUtil {
|
||||
return Stream.of(SignalDatabase.groups()
|
||||
.getPushGroupsContainingMember(recipientId))
|
||||
.filter(g -> g.getMembers().contains(Recipient.self().getId()))
|
||||
.map(GroupTable.GroupRecord::getRecipientId)
|
||||
.map(GroupRecord::getRecipientId)
|
||||
.toList()
|
||||
.size();
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.signal.core.util.ThreadUtil;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.database.DistributionListTables;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.GroupTable.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.RecipientTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListRecord;
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadTable;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupChangeBusyException;
|
||||
import org.thoughtcrime.securesms.groups.GroupChangeException;
|
||||
@@ -301,7 +302,7 @@ public class RecipientUtil {
|
||||
GroupTable groupDatabase = SignalDatabase.groups();
|
||||
return groupDatabase.getPushGroupsContainingMember(recipient.getId())
|
||||
.stream()
|
||||
.anyMatch(GroupTable.GroupRecord::isV2Group);
|
||||
.anyMatch(GroupRecord::isV2Group);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -11,6 +11,7 @@ import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.contacts.sync.ContactDiscovery;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.IdentityRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupChangeException;
|
||||
@@ -106,11 +107,11 @@ final class RecipientDialogRepository {
|
||||
void getGroupMembership(@NonNull Consumer<List<RecipientId>> onComplete) {
|
||||
SimpleTask.run(SignalExecutors.UNBOUNDED,
|
||||
() -> {
|
||||
GroupTable groupDatabase = SignalDatabase.groups();
|
||||
List<GroupTable.GroupRecord> groupRecords = groupDatabase.getPushGroupsContainingMember(recipientId);
|
||||
ArrayList<RecipientId> groupRecipients = new ArrayList<>(groupRecords.size());
|
||||
GroupTable groupDatabase = SignalDatabase.groups();
|
||||
List<GroupRecord> groupRecords = groupDatabase.getPushGroupsContainingMember(recipientId);
|
||||
ArrayList<RecipientId> groupRecipients = new ArrayList<>(groupRecords.size());
|
||||
|
||||
for (GroupTable.GroupRecord groupRecord : groupRecords) {
|
||||
for (GroupRecord groupRecord : groupRecords) {
|
||||
groupRecipients.add(groupRecord.getRecipientId());
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.thoughtcrime.securesms.database.RecipientTable;
|
||||
import org.thoughtcrime.securesms.database.SearchTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadTable;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.Mention;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
@@ -174,7 +175,7 @@ public class SearchRepository {
|
||||
|
||||
Set<RecipientId> groupsByTitleIds = new LinkedHashSet<>();
|
||||
|
||||
GroupTable.GroupRecord record;
|
||||
GroupRecord record;
|
||||
try (GroupTable.Reader reader = SignalDatabase.groups().queryGroupsByTitle(query, true, false, false)) {
|
||||
while ((record = reader.getNext()) != null) {
|
||||
groupsByTitleIds.add(record.getRecipientId());
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.CallTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.events.GroupCallPeekEvent;
|
||||
import org.thoughtcrime.securesms.events.WebRtcViewModel;
|
||||
@@ -748,9 +749,9 @@ private void processStateless(@NonNull Function1<WebRtcEphemeralState, WebRtcEph
|
||||
@Override
|
||||
public void onGroupCallRingUpdate(@NonNull byte[] groupIdBytes, long ringId, @NonNull UUID sender, @NonNull CallManager.RingUpdate ringUpdate) {
|
||||
try {
|
||||
GroupId.V2 groupId = GroupId.v2(new GroupIdentifier(groupIdBytes));
|
||||
GroupTable.GroupRecord group = SignalDatabase.groups().getGroup(groupId).orElse(null);
|
||||
Recipient senderRecipient = Recipient.externalPush(ServiceId.from(sender));
|
||||
GroupId.V2 groupId = GroupId.v2(new GroupIdentifier(groupIdBytes));
|
||||
GroupRecord group = SignalDatabase.groups().getGroup(groupId).orElse(null);
|
||||
Recipient senderRecipient = Recipient.externalPush(ServiceId.from(sender));
|
||||
|
||||
if (group != null &&
|
||||
group.isActive() &&
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.RecipientTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.groups.BadGroupIdException;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
@@ -46,8 +47,8 @@ public final class GroupV1RecordProcessor extends DefaultStorageRecordProcessor<
|
||||
@Override
|
||||
boolean isInvalid(@NonNull SignalGroupV1Record remote) {
|
||||
try {
|
||||
GroupId.V1 id = GroupId.v1(remote.getGroupId());
|
||||
Optional<GroupTable.GroupRecord> v2Record = groupDatabase.getGroup(id.deriveV2MigrationGroupId());
|
||||
GroupId.V1 id = GroupId.v1(remote.getGroupId());
|
||||
Optional<GroupRecord> v2Record = groupDatabase.getGroup(id.deriveV2MigrationGroupId());
|
||||
|
||||
if (v2Record.isPresent()) {
|
||||
Log.w(TAG, "We already have an upgraded V2 group for this V1 group -- marking as invalid.");
|
||||
|
||||
@@ -29,8 +29,8 @@ import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.WebRtcCallActivity;
|
||||
import org.thoughtcrime.securesms.contacts.sync.ContactDiscovery;
|
||||
import org.thoughtcrime.securesms.conversation.ConversationIntents;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.groups.ui.invitesandrequests.joining.GroupJoinBottomSheetDialogFragment;
|
||||
@@ -237,7 +237,7 @@ public class CommunicationActions {
|
||||
GroupId.V2 groupId = GroupId.v2(groupInviteLinkUrl.getGroupMasterKey());
|
||||
|
||||
SimpleTask.run(SignalExecutors.BOUNDED, () -> {
|
||||
GroupTable.GroupRecord group = SignalDatabase.groups().getGroup(groupId).orElse(null);
|
||||
GroupRecord group = SignalDatabase.groups().getGroup(groupId).orElse(null);
|
||||
|
||||
return group != null && group.isActive() ? Recipient.resolved(group.getRecipientId())
|
||||
: null;
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.mms.MessageGroupContext;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
@@ -94,7 +95,7 @@ public final class GroupUtil {
|
||||
{
|
||||
if (groupId.isV2()) {
|
||||
GroupTable groupDatabase = SignalDatabase.groups();
|
||||
GroupTable.GroupRecord groupRecord = groupDatabase.requireGroup(groupId);
|
||||
GroupRecord groupRecord = groupDatabase.requireGroup(groupId);
|
||||
GroupTable.V2GroupProperties v2GroupProperties = groupRecord.requireV2GroupProperties();
|
||||
SignalServiceGroupV2 group = SignalServiceGroupV2.newBuilder(v2GroupProperties.getGroupMasterKey())
|
||||
.withRevision(v2GroupProperties.getGroupRevision())
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.thoughtcrime.securesms.database.IdentityTable;
|
||||
import org.thoughtcrime.securesms.database.MessageTable;
|
||||
import org.thoughtcrime.securesms.database.MessageTable.InsertResult;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.IdentityRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
@@ -67,7 +68,7 @@ public final class IdentityUtil {
|
||||
|
||||
try (GroupTable.Reader reader = groupDatabase.getGroups()) {
|
||||
|
||||
GroupTable.GroupRecord groupRecord;
|
||||
GroupRecord groupRecord;
|
||||
|
||||
while ((groupRecord = reader.getNext()) != null) {
|
||||
if (groupRecord.getMembers().contains(recipient.getId()) && groupRecord.isActive() && !groupRecord.isMms()) {
|
||||
@@ -138,7 +139,7 @@ public final class IdentityUtil {
|
||||
GroupTable groupDatabase = SignalDatabase.groups();
|
||||
|
||||
try (GroupTable.Reader reader = groupDatabase.getGroups()) {
|
||||
GroupTable.GroupRecord groupRecord;
|
||||
GroupRecord groupRecord;
|
||||
|
||||
while ((groupRecord = reader.getNext()) != null) {
|
||||
if (groupRecord.getMembers().contains(recipientId) && groupRecord.isActive()) {
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedString
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedTimer
|
||||
import org.signal.storageservice.protos.groups.local.EnabledState
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupHistoryEntry
|
||||
@@ -99,7 +100,7 @@ class GroupChangeData(private val revision: Int, private val groupOperations: Gr
|
||||
class GroupStateTestData(private val masterKey: GroupMasterKey, private val groupOperations: GroupsV2Operations.GroupOperations? = null) {
|
||||
|
||||
var localState: DecryptedGroup? = null
|
||||
var groupRecord: Optional<GroupTable.GroupRecord> = Optional.empty()
|
||||
var groupRecord: Optional<GroupRecord> = Optional.empty()
|
||||
var serverState: DecryptedGroup? = null
|
||||
var changeSet: ChangeSet? = null
|
||||
var groupChange: GroupChange? = null
|
||||
@@ -172,9 +173,9 @@ fun groupRecord(
|
||||
avatarDigest: ByteArray = ByteArray(0),
|
||||
mms: Boolean = false,
|
||||
distributionId: DistributionId? = null
|
||||
): Optional<GroupTable.GroupRecord> {
|
||||
): Optional<GroupRecord> {
|
||||
return Optional.of(
|
||||
GroupTable.GroupRecord(
|
||||
GroupRecord(
|
||||
id,
|
||||
recipientId,
|
||||
decryptedGroup.title,
|
||||
|
||||
@@ -4,6 +4,10 @@ package org.thoughtcrime.securesms.groups
|
||||
|
||||
import android.app.Application
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.slot
|
||||
import io.mockk.verify
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.hamcrest.Matchers
|
||||
import org.hamcrest.Matchers.`is`
|
||||
@@ -11,9 +15,6 @@ import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentCaptor
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.Mockito.mock
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import org.signal.core.util.Hex
|
||||
@@ -71,8 +72,6 @@ class GroupManagerV2Test_edit {
|
||||
private lateinit var sendGroupUpdateHelper: GroupManagerV2.SendGroupUpdateHelper
|
||||
private lateinit var groupOperations: GroupsV2Operations.GroupOperations
|
||||
|
||||
private lateinit var patchedDecryptedGroup: ArgumentCaptor<DecryptedGroup>
|
||||
|
||||
private lateinit var manager: GroupManagerV2
|
||||
|
||||
@get:Rule
|
||||
@@ -87,17 +86,15 @@ class GroupManagerV2Test_edit {
|
||||
|
||||
val clientZkOperations = ClientZkOperations(server.getServerPublicParams())
|
||||
|
||||
groupTable = mock(GroupTable::class.java)
|
||||
groupsV2API = mock(GroupsV2Api::class.java)
|
||||
groupTable = mockk()
|
||||
groupsV2API = mockk()
|
||||
groupsV2Operations = GroupsV2Operations(clientZkOperations, 1000)
|
||||
groupsV2Authorization = mock(GroupsV2Authorization::class.java)
|
||||
groupsV2StateProcessor = mock(GroupsV2StateProcessor::class.java)
|
||||
groupCandidateHelper = mock(GroupCandidateHelper::class.java)
|
||||
sendGroupUpdateHelper = mock(GroupManagerV2.SendGroupUpdateHelper::class.java)
|
||||
groupsV2Authorization = mockk(relaxed = true)
|
||||
groupsV2StateProcessor = mockk()
|
||||
groupCandidateHelper = mockk()
|
||||
sendGroupUpdateHelper = mockk()
|
||||
groupOperations = groupsV2Operations.forGroup(groupSecretParams)
|
||||
|
||||
patchedDecryptedGroup = ArgumentCaptor.forClass(DecryptedGroup::class.java)
|
||||
|
||||
manager = GroupManagerV2(
|
||||
ApplicationProvider.getApplicationContext(),
|
||||
groupTable,
|
||||
@@ -115,12 +112,11 @@ class GroupManagerV2Test_edit {
|
||||
val data = GroupStateTestData(masterKey, groupOperations)
|
||||
data.init()
|
||||
|
||||
Mockito.doReturn(data.groupRecord).`when`(groupTable).getGroup(groupId)
|
||||
Mockito.doReturn(data.groupRecord.get()).`when`(groupTable).requireGroup(groupId)
|
||||
|
||||
Mockito.doReturn(GroupManagerV2.RecipientAndThread(Recipient.UNKNOWN, 1)).`when`(sendGroupUpdateHelper).sendGroupUpdate(Mockito.eq(masterKey), Mockito.any(), Mockito.any(), Mockito.anyBoolean())
|
||||
|
||||
Mockito.doReturn(data.groupChange!!).`when`(groupsV2API).patchGroup(Mockito.any(), Mockito.any(), Mockito.any())
|
||||
every { groupTable.getGroup(groupId) } returns data.groupRecord
|
||||
every { groupTable.requireGroup(groupId) } returns data.groupRecord.get()
|
||||
every { groupTable.update(any<GroupId.V2>(), any()) } returns Unit
|
||||
every { sendGroupUpdateHelper.sendGroupUpdate(masterKey, any(), any(), any()) } returns GroupManagerV2.RecipientAndThread(Recipient.UNKNOWN, 1)
|
||||
every { groupsV2API.patchGroup(any(), any(), any()) } returns data.groupChange!!
|
||||
}
|
||||
|
||||
private fun editGroup(perform: GroupManagerV2.GroupEditor.() -> Unit) {
|
||||
@@ -128,8 +124,9 @@ class GroupManagerV2Test_edit {
|
||||
}
|
||||
|
||||
private fun then(then: (DecryptedGroup) -> Unit) {
|
||||
Mockito.verify(groupTable).update(Mockito.eq(groupId), patchedDecryptedGroup.capture())
|
||||
then(patchedDecryptedGroup.value)
|
||||
val decryptedGroupArg = slot<DecryptedGroup>()
|
||||
verify { groupTable.update(groupId, capture(decryptedGroupArg)) }
|
||||
then(decryptedGroupArg.captured)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+37
-39
@@ -2,6 +2,10 @@ package org.thoughtcrime.securesms.groups.v2.processing
|
||||
|
||||
import android.app.Application
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.verify
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.hamcrest.Matchers.both
|
||||
import org.hamcrest.Matchers.hasItem
|
||||
@@ -13,18 +17,6 @@ import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentCaptor
|
||||
import org.mockito.ArgumentMatchers.anyLong
|
||||
import org.mockito.ArgumentMatchers.eq
|
||||
import org.mockito.Mockito.any
|
||||
import org.mockito.Mockito.doCallRealMethod
|
||||
import org.mockito.Mockito.doReturn
|
||||
import org.mockito.Mockito.isA
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.Mockito.reset
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.kotlin.anyOrNull
|
||||
import org.mockito.kotlin.doNothing
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import org.signal.core.util.Hex.fromStringCondensed
|
||||
@@ -48,6 +40,7 @@ import org.thoughtcrime.securesms.database.setNewTitle
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.groups.GroupsV2Authorization
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager
|
||||
import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob
|
||||
import org.thoughtcrime.securesms.logging.CustomSignalProtocolLogger
|
||||
import org.thoughtcrime.securesms.testutil.SystemOutLogger
|
||||
@@ -77,6 +70,7 @@ class GroupsV2StateProcessorTest {
|
||||
private lateinit var groupsV2API: GroupsV2Api
|
||||
private lateinit var groupsV2Authorization: GroupsV2Authorization
|
||||
private lateinit var profileAndMessageHelper: GroupsV2StateProcessor.ProfileAndMessageHelper
|
||||
private lateinit var jobManager: JobManager
|
||||
|
||||
private lateinit var processor: GroupsV2StateProcessor.StateProcessorForGroup
|
||||
|
||||
@@ -88,25 +82,29 @@ class GroupsV2StateProcessorTest {
|
||||
Log.initialize(SystemOutLogger())
|
||||
SignalProtocolLoggerProvider.setProvider(CustomSignalProtocolLogger())
|
||||
|
||||
groupTable = mock(GroupTable::class.java)
|
||||
recipientTable = mock(RecipientTable::class.java)
|
||||
groupsV2API = mock(GroupsV2Api::class.java)
|
||||
groupsV2Authorization = mock(GroupsV2Authorization::class.java)
|
||||
profileAndMessageHelper = mock(GroupsV2StateProcessor.ProfileAndMessageHelper::class.java)
|
||||
groupTable = mockk(relaxed = true)
|
||||
recipientTable = mockk()
|
||||
groupsV2API = mockk()
|
||||
groupsV2Authorization = mockk(relaxed = true)
|
||||
profileAndMessageHelper = mockk(relaxed = true)
|
||||
jobManager = mockk(relaxed = true)
|
||||
|
||||
mockkStatic(ApplicationDependencies::class)
|
||||
every { ApplicationDependencies.getJobManager() } returns jobManager
|
||||
|
||||
processor = GroupsV2StateProcessor.StateProcessorForGroup(serviceIds, ApplicationProvider.getApplicationContext(), groupTable, groupsV2API, groupsV2Authorization, masterKey, profileAndMessageHelper)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
reset(ApplicationDependencies.getJobManager())
|
||||
// reset(ApplicationDependencies.getJobManager())
|
||||
}
|
||||
|
||||
private fun given(init: GroupStateTestData.() -> Unit) {
|
||||
val data = givenData(init)
|
||||
|
||||
doReturn(data.groupRecord).`when`(groupTable).getGroup(any(GroupId.V2::class.java))
|
||||
doReturn(!data.groupRecord.isPresent).`when`(groupTable).isUnknownGroup(any())
|
||||
every { groupTable.getGroup(any<GroupId.V2>()) } returns data.groupRecord
|
||||
every { groupTable.isUnknownGroup(any()) } returns !data.groupRecord.isPresent
|
||||
|
||||
data.serverState?.let { serverState ->
|
||||
val testPartial = object : PartialDecryptedGroup(null, serverState, null, null) {
|
||||
@@ -114,12 +112,13 @@ class GroupsV2StateProcessorTest {
|
||||
return serverState
|
||||
}
|
||||
}
|
||||
doReturn(testPartial).`when`(groupsV2API).getPartialDecryptedGroup(any(), any())
|
||||
doReturn(serverState).`when`(groupsV2API).getGroup(any(), any())
|
||||
|
||||
every { groupsV2API.getPartialDecryptedGroup(any(), any()) } returns testPartial
|
||||
every { groupsV2API.getGroup(any(), any()) } returns serverState
|
||||
}
|
||||
|
||||
data.changeSet?.let { changeSet ->
|
||||
doReturn(changeSet.toApiResponse()).`when`(groupsV2API).getGroupHistoryPage(any(), eq(data.requestedRevision), any(), eq(data.includeFirst))
|
||||
every { groupsV2API.getGroupHistoryPage(any(), data.requestedRevision, any(), data.includeFirst) } returns changeSet.toApiResponse()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,15 +305,14 @@ class GroupsV2StateProcessorTest {
|
||||
apiCallParameters(2, true)
|
||||
}
|
||||
|
||||
doReturn(true).`when`(groupTable).isUnknownGroup(any())
|
||||
every { groupTable.isUnknownGroup(any()) } returns true
|
||||
|
||||
val result = processor.updateLocalGroupToRevision(2, 0, DecryptedGroupChange.getDefaultInstance())
|
||||
|
||||
assertThat("local should update to revision added", result.groupState, `is`(GroupsV2StateProcessor.GroupState.GROUP_UPDATED))
|
||||
assertThat("revision matches peer revision added", result.latestServer!!.revision, `is`(2))
|
||||
assertThat("title matches that as it was in revision added", result.latestServer!!.title, `is`("Baking Signal for Science"))
|
||||
|
||||
verify(ApplicationDependencies.getJobManager()).add(isA(RequestGroupV2InfoJob::class.java))
|
||||
verify { jobManager.add(ofType(RequestGroupV2InfoJob::class)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -406,7 +404,7 @@ class GroupsV2StateProcessorTest {
|
||||
assertThat("local should update to server", result.groupState, `is`(GroupsV2StateProcessor.GroupState.GROUP_UPDATED))
|
||||
assertThat("revision matches revision approved at", result.latestServer!!.revision, `is`(3))
|
||||
assertThat("title matches revision approved at", result.latestServer!!.title, `is`("Beam me up"))
|
||||
verify(ApplicationDependencies.getJobManager()).add(isA(RequestGroupV2InfoJob::class.java))
|
||||
verify { jobManager.add(ofType(RequestGroupV2InfoJob::class)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -458,7 +456,7 @@ class GroupsV2StateProcessorTest {
|
||||
}
|
||||
}
|
||||
}
|
||||
doReturn(secondApiCallChangeSet.changeSet!!.toApiResponse()).`when`(groupsV2API).getGroupHistoryPage(any(), eq(100), any(), eq(true))
|
||||
every { groupsV2API.getGroupHistoryPage(any(), 100, any(), true) } returns secondApiCallChangeSet.changeSet!!.toApiResponse()
|
||||
|
||||
val result = processor.updateLocalGroupToRevision(GroupsV2StateProcessor.LATEST, 0, null)
|
||||
|
||||
@@ -474,10 +472,11 @@ class GroupsV2StateProcessorTest {
|
||||
fun missedMemberAddResolvesWithMultipleRevisionUpdate() {
|
||||
val secondOther = member(ServiceId.from(UUID.randomUUID()))
|
||||
|
||||
val updateMessageContextCapture = ArgumentCaptor.forClass(DecryptedGroupV2Context::class.java)
|
||||
profileAndMessageHelper.masterKey = masterKey
|
||||
doCallRealMethod().`when`(profileAndMessageHelper).insertUpdateMessages(anyLong(), anyOrNull(), any())
|
||||
doNothing().`when`(profileAndMessageHelper).storeMessage(updateMessageContextCapture.capture(), anyLong())
|
||||
|
||||
val updateMessageContextArgs = mutableListOf<DecryptedGroupV2Context>()
|
||||
every { profileAndMessageHelper.insertUpdateMessages(any(), any(), any()) } answers { callOriginal() }
|
||||
every { profileAndMessageHelper.storeMessage(capture(updateMessageContextArgs), any()) } returns Unit
|
||||
|
||||
given {
|
||||
localState(
|
||||
@@ -513,8 +512,7 @@ class GroupsV2StateProcessorTest {
|
||||
assertThat("local should update to server", result.groupState, `is`(GroupsV2StateProcessor.GroupState.GROUP_UPDATED))
|
||||
assertThat("members contains second other", result.latestServer!!.membersList, hasItem(secondOther))
|
||||
|
||||
val allUpdateMessageContexts = updateMessageContextCapture.allValues
|
||||
assertThat("group update messages contains new member add", allUpdateMessageContexts.map { it.change.newMembersList }, hasItem(hasItem(secondOther)))
|
||||
assertThat("group update messages contains new member add", updateMessageContextArgs.map { it.change.newMembersList }, hasItem(hasItem(secondOther)))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -525,10 +523,11 @@ class GroupsV2StateProcessorTest {
|
||||
fun missedMemberAddResolvesWithForcedUpdate() {
|
||||
val secondOther = member(ServiceId.from(UUID.randomUUID()))
|
||||
|
||||
val updateMessageContextCapture = ArgumentCaptor.forClass(DecryptedGroupV2Context::class.java)
|
||||
profileAndMessageHelper.masterKey = masterKey
|
||||
doCallRealMethod().`when`(profileAndMessageHelper).insertUpdateMessages(anyLong(), anyOrNull(), any())
|
||||
doNothing().`when`(profileAndMessageHelper).storeMessage(updateMessageContextCapture.capture(), anyLong())
|
||||
|
||||
val updateMessageContextArgs = mutableListOf<DecryptedGroupV2Context>()
|
||||
every { profileAndMessageHelper.insertUpdateMessages(any(), any(), any()) } answers { callOriginal() }
|
||||
every { profileAndMessageHelper.storeMessage(capture(updateMessageContextArgs), any()) } returns Unit
|
||||
|
||||
given {
|
||||
localState(
|
||||
@@ -548,12 +547,11 @@ class GroupsV2StateProcessorTest {
|
||||
assertThat("members contains second other", result.latestServer!!.membersList, hasItem(secondOther))
|
||||
assertThat("title should be updated", result.latestServer!!.title, `is`("Changed"))
|
||||
|
||||
val allUpdateMessageContexts = updateMessageContextCapture.allValues
|
||||
assertThat("group update messages contains new member add", allUpdateMessageContexts.map { it.change.newMembersList }, hasItem(hasItem(secondOther)))
|
||||
assertThat("group update messages contains new member add", updateMessageContextArgs.map { it.change.newMembersList }, hasItem(hasItem(secondOther)))
|
||||
|
||||
assertThat(
|
||||
"group update messages contains title change",
|
||||
allUpdateMessageContexts.map { it.change.newTitle },
|
||||
updateMessageContextArgs.map { it.change.newTitle },
|
||||
hasItem(both<DecryptedString>(notNullValue()).and(hasProperty("value", `is`("Changed"))))
|
||||
)
|
||||
}
|
||||
|
||||
+2
-1
@@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.jobmanager.migrations;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobMigration;
|
||||
@@ -34,7 +35,7 @@ public class SenderKeyDistributionSendJobRecipientMigrationTest {
|
||||
.putBlobAsString("group_id", GROUP_ID.getDecodedId())
|
||||
.build());
|
||||
|
||||
GroupTable.GroupRecord mockGroup = mock(GroupTable.GroupRecord.class);
|
||||
GroupRecord mockGroup = mock(GroupRecord.class);
|
||||
when(mockGroup.getRecipientId()).thenReturn(RecipientId.from(2));
|
||||
when(mockDatabase.getGroup(GROUP_ID)).thenReturn(Optional.of(mockGroup));
|
||||
|
||||
|
||||
@@ -92,6 +92,16 @@ fun <T> Cursor.readToSingleObject(serializer: Serializer<T, Cursor>): T? {
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> Cursor.readToSingleObject(mapper: (Cursor) -> T): T? {
|
||||
return use {
|
||||
if (it.moveToFirst()) {
|
||||
mapper(it)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun Cursor.readToSingleInt(defaultValue: Int = 0): Int {
|
||||
return use {
|
||||
|
||||
Reference in New Issue
Block a user