diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationData.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationData.kt index 4a4d7b7205..3831b73116 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationData.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationData.kt @@ -1,6 +1,7 @@ package org.thoughtcrime.securesms.conversation import org.thoughtcrime.securesms.recipients.Recipient +import org.whispersystems.signalservice.api.push.ServiceId /** * Represents metadata about a conversation. @@ -15,7 +16,8 @@ data class ConversationData( val threadSize: Int, val messageRequestData: MessageRequestData, @get:JvmName("showUniversalExpireTimerMessage") val showUniversalExpireTimerMessage: Boolean, - val unreadCount: Int + val unreadCount: Int, + val groupMemberAcis: List ) { fun shouldJumpToMessage(): Boolean { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationRepository.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationRepository.java index a9de722b63..431eca7574 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationRepository.java @@ -30,6 +30,7 @@ import org.thoughtcrime.securesms.util.ConversationUtil; import org.thoughtcrime.securesms.util.MessageRecordUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; +import org.whispersystems.signalservice.api.push.ServiceId; import java.io.IOException; import java.io.InputStream; @@ -110,6 +111,13 @@ public class ConversationRepository { messageRequestData = new ConversationData.MessageRequestData(isMessageRequestAccepted, isConversationHidden, recipientIsKnownOrHasGroupsInCommon, isGroup); } + List groupMemberAcis; + if (conversationRecipient.isPushV2Group()) { + groupMemberAcis = conversationRecipient.getParticipantAcis(); + } else { + groupMemberAcis = Collections.emptyList(); + } + if (SignalStore.settings().getUniversalExpireTimer() != 0 && conversationRecipient.getExpiresInSeconds() == 0 && !conversationRecipient.isGroup() && @@ -119,7 +127,7 @@ public class ConversationRepository { showUniversalExpireTimerUpdate = true; } - return new ConversationData(conversationRecipient, threadId, lastSeen, lastSeenPosition, lastScrolledPosition, jumpToPosition, threadSize, messageRequestData, showUniversalExpireTimerUpdate, metadata.getUnreadCount()); + return new ConversationData(conversationRecipient, threadId, lastSeen, lastSeenPosition, lastScrolledPosition, jumpToPosition, threadSize, messageRequestData, showUniversalExpireTimerUpdate, metadata.getUnreadCount(), groupMemberAcis); } public void markGiftBadgeRevealed(long messageId) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/colors/Colorizer.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/colors/Colorizer.kt index 3a0ba05025..7ad167277e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/colors/Colorizer.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/colors/Colorizer.kt @@ -1,12 +1,12 @@ package org.thoughtcrime.securesms.conversation.colors import android.content.Context -import android.graphics.Color import androidx.annotation.ColorInt import androidx.core.content.ContextCompat import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId +import org.whispersystems.signalservice.api.push.ServiceId /** * Helper class for all things ChatColors. @@ -18,8 +18,12 @@ import org.thoughtcrime.securesms.recipients.RecipientId class Colorizer { private var colorsHaveBeenSet = false + + @Deprecated("Not needed for CFv2") private val groupSenderColors: MutableMap = mutableMapOf() + private val groupMembers: LinkedHashSet = linkedSetOf() + @ColorInt fun getOutgoingBodyTextColor(context: Context): Int { return ContextCompat.getColor(context, R.color.conversation_outgoing_body_color) @@ -63,8 +67,26 @@ class Colorizer { } @ColorInt - fun getIncomingGroupSenderColor(context: Context, recipient: Recipient): Int = groupSenderColors[recipient.id]?.getColor(context) ?: getDefaultColor(context, recipient.id) + fun getIncomingGroupSenderColor(context: Context, recipient: Recipient): Int { + return if (groupMembers.isEmpty()) { + groupSenderColors[recipient.id]?.getColor(context) ?: getDefaultColor(context, recipient) + } else { + val memberPosition = groupMembers.indexOf(recipient.requireServiceId()) + if (memberPosition >= 0) { + val colorPosition = memberPosition % ChatColorsPalette.Names.all.size + ChatColorsPalette.Names.all[colorPosition].getColor(context) + } else { + getDefaultColor(context, recipient) + } + } + } + + fun onGroupMembershipChanged(serviceIds: List) { + groupMembers.addAll(serviceIds.sortedBy { it.toString() }) + } + + @Deprecated("Not needed for CFv2", ReplaceWith("onGroupMembershipChanged")) fun onNameColorsChanged(nameColorMap: Map) { groupSenderColors.clear() groupSenderColors.putAll(nameColorMap) @@ -72,13 +94,13 @@ class Colorizer { } @ColorInt - private fun getDefaultColor(context: Context, recipientId: RecipientId): Int { + private fun getDefaultColor(context: Context, recipient: Recipient): Int { return if (colorsHaveBeenSet) { val color = ChatColorsPalette.Names.all[groupSenderColors.size % ChatColorsPalette.Names.all.size] - groupSenderColors[recipientId] = color + groupSenderColors[recipient.id] = color return color.getColor(context) } else { - Color.TRANSPARENT + getIncomingBodyTextColor(context, recipient.hasWallpaper()) } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/colors/GroupAuthorNameColorHelper.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/colors/GroupAuthorNameColorHelper.kt index 9e8160dd89..f0c0355f5a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/colors/GroupAuthorNameColorHelper.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/colors/GroupAuthorNameColorHelper.kt @@ -2,11 +2,9 @@ package org.thoughtcrime.securesms.conversation.colors 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.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId -import org.whispersystems.signalservice.api.push.ServiceId /** * Class to assist managing the colors of author names in the UI in groups. @@ -18,35 +16,6 @@ class GroupAuthorNameColorHelper { /** Needed so that we have a full history of current *and* past members (so colors don't change when someone leaves) */ private val fullMemberCache: MutableMap> = mutableMapOf() - private val fullMemberServiceIdsCache: MutableMap> = mutableMapOf() - - /** - * Given a [GroupRecord], returns a map of member -> name color. - */ - fun getColorMap(groupRecord: GroupRecord): Map { - if (!groupRecord.isV2Group) { - return getColorMap(groupRecord.id) - } - - val cachedServiceIds: Set = fullMemberServiceIdsCache[groupRecord.id] ?: setOf() - val allIds: Set = cachedServiceIds + groupRecord.decryptedMemberServiceIds.toSet() - - fullMemberServiceIdsCache[groupRecord.id] = allIds - - val selfId = Recipient.self().requireServiceId() - val members: List = allIds - .filter { it != selfId } - .sortedBy { it.toString() } - - val allColors: List = ChatColorsPalette.Names.all - - val colors: MutableMap = HashMap() - for (i in members.indices) { - colors[RecipientId.from(members[i])] = allColors[i % allColors.size] - } - - return colors.toMap() - } /** * Given a [GroupId], returns a map of member -> name color. diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt index a20f921d25..f248d0e9a9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt @@ -766,6 +766,7 @@ class ConversationFragment : .doOnSuccess { state -> SignalLocalMetrics.ConversationOpen.onDataLoaded() conversationItemDecorations.setFirstUnreadCount(state.meta.unreadCount) + colorizer.onGroupMembershipChanged(state.meta.groupMemberAcis) } .observeOn(AndroidSchedulers.mainThread()) .doOnSuccess { state -> @@ -817,10 +818,9 @@ class ConversationFragment : .subscribeBy(onNext = this::presentScrollButtons) disposables += viewModel - .nameColorsMap - .observeOn(AndroidSchedulers.mainThread()) + .groupMemberServiceIds .subscribeBy(onNext = { - colorizer.onNameColorsChanged(it) + colorizer.onGroupMembershipChanged(it) adapter.updateNameColors() }) @@ -1059,8 +1059,6 @@ class ConversationFragment : } composeText.setMessageSendType(MessageSendType.SignalMessageSendType) - - colorizer.onNameColorsChanged(inputReadyState.groupNameColors) } private fun presentIdentityRecordsState(identityRecordsState: IdentityRecordsState) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationRepository.kt index 4f1ab11819..2f53275689 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationRepository.kt @@ -44,8 +44,6 @@ import org.thoughtcrime.securesms.contactshare.Contact import org.thoughtcrime.securesms.contactshare.ContactUtil import org.thoughtcrime.securesms.conversation.ConversationMessage import org.thoughtcrime.securesms.conversation.MessageSendType -import org.thoughtcrime.securesms.conversation.colors.GroupAuthorNameColorHelper -import org.thoughtcrime.securesms.conversation.colors.NameColor import org.thoughtcrime.securesms.conversation.mutiselect.MultiselectPart import org.thoughtcrime.securesms.conversation.v2.RequestReviewState.GroupReviewState import org.thoughtcrime.securesms.conversation.v2.RequestReviewState.IndividualReviewState @@ -159,16 +157,6 @@ class ConversationRepository( }.subscribeOn(Schedulers.io()) } - /** - * Generates the name color-map for groups. - */ - fun getNameColorsMap( - group: GroupRecord, - groupAuthorNameColorHelper: GroupAuthorNameColorHelper - ): Map { - return groupAuthorNameColorHelper.getColorMap(group) - } - fun sendReactionRemoval(messageRecord: MessageRecord, oldRecord: ReactionRecord): Completable { return Completable.fromAction { MessageSender.sendReactionRemoval( diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt index 8442ce0a7b..19341cef3e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt @@ -32,8 +32,6 @@ import org.thoughtcrime.securesms.components.reminder.Reminder import org.thoughtcrime.securesms.contactshare.Contact import org.thoughtcrime.securesms.conversation.ConversationMessage import org.thoughtcrime.securesms.conversation.ScheduledMessagesRepository -import org.thoughtcrime.securesms.conversation.colors.GroupAuthorNameColorHelper -import org.thoughtcrime.securesms.conversation.colors.NameColor import org.thoughtcrime.securesms.conversation.mutiselect.MultiselectPart import org.thoughtcrime.securesms.conversation.v2.data.ConversationElementKey import org.thoughtcrime.securesms.database.DatabaseObserver @@ -68,6 +66,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.hasGiftBadge import org.thoughtcrime.securesms.util.rx.RxStore import org.thoughtcrime.securesms.wallpaper.ChatWallpaper +import org.whispersystems.signalservice.api.push.ServiceId import java.util.Optional import kotlin.time.Duration @@ -84,7 +83,6 @@ class ConversationViewModel( ) : ViewModel() { private val disposables = CompositeDisposable() - private val groupAuthorNameColorHelper = GroupAuthorNameColorHelper() private val scrollButtonStateStore = RxStore(ConversationScrollButtonState()).addTo(disposables) val scrollButtonState: Flowable = scrollButtonStateStore.stateFlowable @@ -107,12 +105,10 @@ class ConversationViewModel( val pagingController = ProxyPagingController() - val nameColorsMap: Observable> = recipientRepository + val groupMemberServiceIds: Observable> = recipientRepository .groupRecord - .filter { it.isPresent } - .map { it.get() } - .distinctUntilChanged { previous, next -> previous.hasSameMembers(next) } - .map { repository.getNameColorsMap(it, groupAuthorNameColorHelper) } + .filter { it.isPresent && it.get().isV2Group } + .map { it.get().requireV2GroupProperties().getMemberServiceIds() } .distinctUntilChanged() .observeOn(AndroidSchedulers.mainThread()) @@ -217,7 +213,6 @@ class ConversationViewModel( conversationRecipient = recipient, messageRequestState = messageRequestRepository.getMessageRequestState(recipient, threadId), groupRecord = groupRecord.orNull(), - groupNameColors = groupRecord.map { repository.getNameColorsMap(it, groupAuthorNameColorHelper) }.orElse(emptyMap()), isClientExpired = SignalStore.misc().isClientDeprecated, isUnauthorized = TextSecurePreferences.isUnauthorizedReceived(ApplicationDependencies.getApplication()) ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/InputReadyState.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/InputReadyState.kt index 2dbbadaf07..6e481e6d43 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/InputReadyState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/InputReadyState.kt @@ -5,13 +5,10 @@ package org.thoughtcrime.securesms.conversation.v2 -import org.thoughtcrime.securesms.conversation.colors.NameColor import org.thoughtcrime.securesms.database.GroupTable -import org.thoughtcrime.securesms.database.RecipientTable import org.thoughtcrime.securesms.database.model.GroupRecord import org.thoughtcrime.securesms.messagerequests.MessageRequestState import org.thoughtcrime.securesms.recipients.Recipient -import org.thoughtcrime.securesms.recipients.RecipientId /** * Information necessary for rendering compose input. @@ -21,12 +18,10 @@ data class InputReadyState( val messageRequestState: MessageRequestState, val groupRecord: GroupRecord?, val isClientExpired: Boolean, - val isUnauthorized: Boolean, - val groupNameColors: Map + val isUnauthorized: Boolean ) { private val selfMemberLevel: GroupTable.MemberLevel? = groupRecord?.memberLevel(Recipient.self()) - val isSignalConversation: Boolean = conversationRecipient.registered == RecipientTable.RegisteredState.REGISTERED && Recipient.self().isRegistered val isAnnouncementGroup: Boolean? = groupRecord?.isAnnouncementGroup val isActiveGroup: Boolean? = if (selfMemberLevel == null) null else selfMemberLevel != GroupTable.MemberLevel.NOT_A_MEMBER val isAdmin: Boolean? = selfMemberLevel?.equals(GroupTable.MemberLevel.ADMINISTRATOR) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/GroupTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/GroupTable.kt index 48dfa3955b..c846c02808 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/GroupTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/GroupTable.kt @@ -1294,6 +1294,17 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT return recipients } + + fun getMemberServiceIds(): List { + return decryptedGroup + .membersList + .asSequence() + .map { UuidUtil.fromByteStringOrNull(it.uuid) } + .filterNotNull() + .map { ServiceId.from(it) } + .sortedBy { it.toString() } + .toList() + } } @Throws(BadGroupIdException::class) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadTable.kt index 6062f61483..4068485e5f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadTable.kt @@ -1859,7 +1859,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa null, false, group.isActive, - null + null, + Optional.of(group) ) Recipient(recipientId, details, false) } ?: Recipient.live(recipientId).get() diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupRecord.kt b/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupRecord.kt index 2927e49e57..b99a381a50 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupRecord.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupRecord.kt @@ -13,8 +13,6 @@ 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 org.whispersystems.signalservice.api.push.ServiceId -import org.whispersystems.signalservice.api.util.UuidUtil import java.util.Optional class GroupRecord( @@ -45,22 +43,6 @@ class GroupRecord( } } - /** Valid for v2 groups only */ - val decryptedMemberServiceIds: List by lazy { - if (isV2Group) { - requireV2GroupProperties() - .decryptedGroup - .membersList - .asSequence() - .map { DecryptedGroupUtil.toUuid(it) } - .filterNot { it == UuidUtil.UNKNOWN_UUID } - .map { ServiceId.from(it) } - .toList() - } else { - emptyList() - } - } - /** V1 members that were lost during the V1->V2 migration */ val unmigratedV1Members: List by lazy { if (serializedUnmigratedV1Members.isNullOrEmpty()) { @@ -200,12 +182,4 @@ class GroupRecord( } return false } - - fun hasSameMembers(other: GroupRecord): Boolean { - if (!isV2Group || !other.isV2Group) { - return false - } - - return decryptedMemberServiceIds == other.decryptedMemberServiceIds - } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/LiveRecipient.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/LiveRecipient.java index cf33f9eaaa..2dd91a7a2d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/LiveRecipient.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/LiveRecipient.java @@ -220,10 +220,10 @@ public final class LiveRecipient { avatarId = Optional.of(groupRecord.get().getAvatarId()); } - return new RecipientDetails(title, null, avatarId, false, false, record.getRegistered(), record, members, false, groupRecord.get().isActive(), null); + return new RecipientDetails(title, null, avatarId, false, false, record.getRegistered(), record, members, false, groupRecord.get().isActive(), null, groupRecord); } - return new RecipientDetails(null, null, Optional.empty(), false, false, record.getRegistered(), record, null, false, false, null); + return new RecipientDetails(null, null, Optional.empty(), false, false, record.getRegistered(), record, null, false, false, null, Optional.empty()); } @WorkerThread diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.java index 2f63505ffc..3a96dce69e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.java @@ -33,6 +33,7 @@ import org.thoughtcrime.securesms.database.RecipientTable.UnidentifiedAccessMode import org.thoughtcrime.securesms.database.RecipientTable.VibrateState; import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.model.DistributionListId; +import org.thoughtcrime.securesms.database.model.GroupRecord; import org.thoughtcrime.securesms.database.model.ProfileAvatarFileDetails; import org.thoughtcrime.securesms.database.model.RecipientRecord; import org.thoughtcrime.securesms.database.model.databaseprotos.RecipientExtras; @@ -137,6 +138,7 @@ public class Recipient { private final boolean isReleaseNotesRecipient; private final boolean needsPniSignature; private final CallLinkRoomId callLinkRoomId; + private final Optional groupRecord; /** * Returns a {@link LiveRecipient}, which contains a {@link Recipient} that may or may not be @@ -425,6 +427,7 @@ public class Recipient { this.needsPniSignature = false; this.isActiveGroup = false; this.callLinkRoomId = null; + this.groupRecord = Optional.empty(); } public Recipient(@NonNull RecipientId id, @NonNull RecipientDetails details, boolean resolved) { @@ -482,6 +485,7 @@ public class Recipient { this.needsPniSignature = details.needsPniSignature; this.isActiveGroup = details.isActiveGroup; this.callLinkRoomId = details.callLinkRoomId; + this.groupRecord = details.groupRecord; } public @NonNull RecipientId getId() { @@ -902,6 +906,11 @@ public class Recipient { return new ArrayList<>(participantIds); } + public @NonNull List getParticipantAcis() { + Preconditions.checkState(groupRecord.isPresent()); + return groupRecord.get().requireV2GroupProperties().getMemberServiceIds(); + } + public @NonNull Drawable getFallbackContactPhotoDrawable(Context context, boolean inverted) { return getFallbackContactPhotoDrawable(context, inverted, DEFAULT_FALLBACK_PHOTO_PROVIDER, AvatarUtil.UNDEFINED_SIZE); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientDetails.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientDetails.java index c6f2c23163..76b3c3860d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientDetails.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientDetails.java @@ -16,6 +16,7 @@ import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState; import org.thoughtcrime.securesms.database.RecipientTable.UnidentifiedAccessMode; import org.thoughtcrime.securesms.database.RecipientTable.VibrateState; import org.thoughtcrime.securesms.database.model.DistributionListId; +import org.thoughtcrime.securesms.database.model.GroupRecord; import org.thoughtcrime.securesms.database.model.ProfileAvatarFileDetails; import org.thoughtcrime.securesms.database.model.RecipientRecord; import org.thoughtcrime.securesms.groups.GroupId; @@ -88,6 +89,7 @@ public class RecipientDetails { final boolean isReleaseChannel; final boolean needsPniSignature; final CallLinkRoomId callLinkRoomId; + final Optional groupRecord; public RecipientDetails(@Nullable String groupName, @Nullable String systemContactName, @@ -99,7 +101,8 @@ public class RecipientDetails { @Nullable List participantIds, boolean isReleaseChannel, boolean isActiveGroup, - @Nullable AvatarColor avatarColor) + @Nullable AvatarColor avatarColor, + Optional groupRecord) { this.groupAvatarId = groupAvatarId; this.systemContactPhoto = Util.uri(record.getSystemContactPhotoUri()); @@ -154,6 +157,7 @@ public class RecipientDetails { this.isReleaseChannel = isReleaseChannel; this.needsPniSignature = record.needsPniSignature(); this.callLinkRoomId = record.getCallLinkRoomId(); + this.groupRecord = groupRecord; } private RecipientDetails() { @@ -210,6 +214,7 @@ public class RecipientDetails { this.needsPniSignature = false; this.isActiveGroup = false; this.callLinkRoomId = null; + this.groupRecord = Optional.empty(); } public static @NonNull RecipientDetails forIndividual(@NonNull Context context, @NonNull RecipientRecord settings) { @@ -228,15 +233,15 @@ public class RecipientDetails { } } - return new RecipientDetails(null, settings.getSystemDisplayName(), Optional.empty(), systemContact, isSelf, registeredState, settings, null, isReleaseChannel, false, null); + return new RecipientDetails(null, settings.getSystemDisplayName(), Optional.empty(), systemContact, isSelf, registeredState, settings, null, isReleaseChannel, false, null, Optional.empty()); } public static @NonNull RecipientDetails forDistributionList(String title, @Nullable List members, @NonNull RecipientRecord record) { - return new RecipientDetails(title, null, Optional.empty(), false, false, record.getRegistered(), record, members, false, false, null); + return new RecipientDetails(title, null, Optional.empty(), false, false, record.getRegistered(), record, members, false, false, null, Optional.empty()); } public static @NonNull RecipientDetails forCallLink(String name, @NonNull RecipientRecord record, @NonNull AvatarColor avatarColor) { - return new RecipientDetails(name, null, Optional.empty(), false, false, record.getRegistered(), record, Collections.emptyList(), false, false, avatarColor); + return new RecipientDetails(name, null, Optional.empty(), false, false, record.getRegistered(), record, Collections.emptyList(), false, false, avatarColor, Optional.empty()); } public static @NonNull RecipientDetails forUnknown() { diff --git a/app/src/test/java/org/thoughtcrime/securesms/database/RecipientDatabaseTestUtils.kt b/app/src/test/java/org/thoughtcrime/securesms/database/RecipientDatabaseTestUtils.kt index d52fb5d356..4da48710d2 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/database/RecipientDatabaseTestUtils.kt +++ b/app/src/test/java/org/thoughtcrime/securesms/database/RecipientDatabaseTestUtils.kt @@ -2,10 +2,12 @@ package org.thoughtcrime.securesms.database import android.net.Uri import org.signal.core.util.Bitmask +import org.signal.core.util.toOptional import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential import org.thoughtcrime.securesms.badges.models.Badge import org.thoughtcrime.securesms.conversation.colors.AvatarColor import org.thoughtcrime.securesms.conversation.colors.ChatColors +import org.thoughtcrime.securesms.database.model.GroupRecord import org.thoughtcrime.securesms.database.model.ProfileAvatarFileDetails import org.thoughtcrime.securesms.database.model.RecipientRecord import org.thoughtcrime.securesms.groups.GroupId @@ -85,7 +87,8 @@ object RecipientDatabaseTestUtils { hasGroupsInCommon: Boolean = false, badges: List = emptyList(), isReleaseChannel: Boolean = false, - isActive: Boolean = true + isActive: Boolean = true, + groupRecord: GroupRecord? = null ): Recipient = Recipient( recipientId, RecipientDetails( @@ -159,7 +162,8 @@ object RecipientDatabaseTestUtils { participants, isReleaseChannel, isActive, - null + null, + groupRecord.toOptional() ), resolved )