From 34a228f85eade4df2496a6bd5fcf3bb07250dc0e Mon Sep 17 00:00:00 2001 From: Cody Henthorne Date: Fri, 17 Nov 2023 14:07:21 -0500 Subject: [PATCH] Remove GV1 migration support. --- .../conversation/ConversationSettingsEvent.kt | 4 - .../ConversationSettingsFragment.kt | 3 - .../ConversationSettingsViewModel.kt | 21 +- .../preferences/LegacyGroupPreference.kt | 13 -- .../conversation/ConversationOptionsMenu.kt | 13 -- .../conversation/v2/ConversationFragment.kt | 15 -- .../conversation/v2/DisabledInputView.kt | 2 - .../securesms/database/GroupTable.kt | 16 +- .../securesms/database/RecipientTable.kt | 14 -- .../securesms/database/model/GroupRecord.kt | 13 +- .../securesms/groups/GroupManagerV2.java | 7 - .../securesms/groups/GroupsV1MigratedCache.kt | 46 ---- .../groups/GroupsV1MigrationUtil.java | 216 ------------------ ...igrationInfoBottomSheetDialogFragment.java | 3 +- ...onInitiationBottomSheetDialogFragment.java | 151 ------------ .../GroupsV1MigrationInitiationViewModel.java | 50 ---- .../GroupsV1MigrationRepository.java | 92 -------- .../groups/ui/migration/MigrationResult.java | 5 - .../groups/ui/migration/MigrationState.java | 30 --- .../securesms/jobs/GroupV1MigrationJob.java | 103 --------- .../securesms/jobs/JobManagerFactories.java | 2 +- .../securesms/jobs/PushProcessMessageJob.kt | 3 +- .../MessageRequestRepository.java | 10 +- .../messagerequests/MessageRequestState.java | 9 - .../MessageRequestsBottomView.java | 57 ++--- .../messages/MessageContentProcessor.kt | 6 - .../storage/GroupV2RecordProcessor.java | 23 +- .../res/layout/message_request_bottom_bar.xml | 23 +- .../menu/conversation_mms_group_options.xml | 18 -- app/src/main/res/values/strings.xml | 2 +- 30 files changed, 42 insertions(+), 928 deletions(-) delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigratedCache.kt delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigrationUtil.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationInitiationBottomSheetDialogFragment.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationInitiationViewModel.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationRepository.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/MigrationResult.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/MigrationState.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/GroupV1MigrationJob.java delete mode 100644 app/src/main/res/menu/conversation_mms_group_options.xml diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsEvent.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsEvent.kt index 7de9c6874e..faa7900876 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsEvent.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsEvent.kt @@ -32,8 +32,4 @@ sealed class ConversationSettingsEvent { class ShowMembersAdded( val membersAddedCount: Int ) : ConversationSettingsEvent() - - class InitiateGroupMigration( - val recipientId: RecipientId - ) : ConversationSettingsEvent() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsFragment.kt index 44ff905146..adf8509b4c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsFragment.kt @@ -72,7 +72,6 @@ import org.thoughtcrime.securesms.groups.ui.invitesandrequests.ManagePendingAndR import org.thoughtcrime.securesms.groups.ui.managegroup.dialogs.GroupDescriptionDialog import org.thoughtcrime.securesms.groups.ui.managegroup.dialogs.GroupInviteSentDialog import org.thoughtcrime.securesms.groups.ui.managegroup.dialogs.GroupsLearnMoreBottomSheetDialogFragment -import org.thoughtcrime.securesms.groups.ui.migration.GroupsV1MigrationInitiationBottomSheetDialogFragment import org.thoughtcrime.securesms.mediaoverview.MediaOverviewActivity import org.thoughtcrime.securesms.mediapreview.MediaIntentFactory import org.thoughtcrime.securesms.profiles.edit.CreateProfileActivity @@ -279,7 +278,6 @@ class ConversationSettingsFragment : DSLSettingsFragment( is ConversationSettingsEvent.ShowAddMembersToGroupError -> showAddMembersToGroupError(event) is ConversationSettingsEvent.ShowGroupInvitesSentDialog -> showGroupInvitesSentDialog(event) is ConversationSettingsEvent.ShowMembersAdded -> showMembersAdded(event) - is ConversationSettingsEvent.InitiateGroupMigration -> GroupsV1MigrationInitiationBottomSheetDialogFragment.showForInitiation(parentFragmentManager, event.recipientId) } } } @@ -363,7 +361,6 @@ class ConversationSettingsFragment : DSLSettingsFragment( LegacyGroupPreference.Model( state = groupState.legacyGroupState, onLearnMoreClick = { GroupsLearnMoreBottomSheetDialogFragment.show(parentFragmentManager) }, - onUpgradeClick = { viewModel.initiateGroupUpgrade() }, onMmsWarningClick = { startActivity(Intent(requireContext(), InviteActivity::class.java)) } ) ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsViewModel.kt index cbf8ecbf2f..19319fe476 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsViewModel.kt @@ -30,7 +30,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.recipients.RecipientUtil -import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.livedata.LiveDataUtil import org.thoughtcrime.securesms.util.livedata.Store @@ -119,8 +118,6 @@ sealed class ConversationSettingsViewModel( } } - open fun initiateGroupUpgrade(): Unit = error("This ViewModel does not support this interaction") - private class RecipientSettingsViewModel( private val recipientId: RecipientId, private val callMessageIds: LongArray, @@ -281,7 +278,7 @@ sealed class ConversationSettingsViewModel( ), canModifyBlockedState = RecipientUtil.isBlockable(recipient), specificSettingsState = state.requireGroupSettingsState().copy( - legacyGroupState = getLegacyGroupState(recipient) + legacyGroupState = getLegacyGroupState() ) ) } @@ -390,14 +387,8 @@ sealed class ConversationSettingsViewModel( } } - private fun getLegacyGroupState(recipient: Recipient): LegacyGroupPreference.State { - val showLegacyInfo = recipient.requireGroupId().isV1 - - return if (showLegacyInfo && recipient.participantIds.size > FeatureFlags.groupLimits().hardLimit) { - LegacyGroupPreference.State.TOO_LARGE - } else if (showLegacyInfo) { - LegacyGroupPreference.State.UPGRADE - } else if (groupId.isMms) { + private fun getLegacyGroupState(): LegacyGroupPreference.State { + return if (groupId.isMms) { LegacyGroupPreference.State.MMS_WARNING } else { LegacyGroupPreference.State.NONE @@ -468,12 +459,6 @@ sealed class ConversationSettingsViewModel( override fun unblock() { repository.unblock(groupId) } - - override fun initiateGroupUpgrade() { - repository.getExternalPossiblyMigratedGroupRecipientId(groupId) { - internalEvents.onNext(ConversationSettingsEvent.InitiateGroupMigration(it)) - } - } } class Factory( diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/LegacyGroupPreference.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/LegacyGroupPreference.kt index 8bf4ff074e..0936529dd7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/LegacyGroupPreference.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/LegacyGroupPreference.kt @@ -4,7 +4,6 @@ import android.view.View import androidx.core.content.ContextCompat import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.components.settings.PreferenceModel -import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter import org.thoughtcrime.securesms.util.adapter.mapping.MappingViewHolder @@ -19,7 +18,6 @@ object LegacyGroupPreference { class Model( val state: State, val onLearnMoreClick: () -> Unit, - val onUpgradeClick: () -> Unit, val onMmsWarningClick: () -> Unit ) : PreferenceModel() { override fun areItemsTheSame(newItem: Model): Boolean { @@ -42,15 +40,6 @@ object LegacyGroupPreference { groupInfoText.setOnLinkClickListener { model.onLearnMoreClick() } groupInfoText.setLearnMoreVisible(true) } - State.UPGRADE -> { - groupInfoText.setText(R.string.ManageGroupActivity_legacy_group_upgrade) - groupInfoText.setOnLinkClickListener { model.onUpgradeClick() } - groupInfoText.setLearnMoreVisible(true, R.string.ManageGroupActivity_upgrade_this_group) - } - State.TOO_LARGE -> { - groupInfoText.text = context.getString(R.string.ManageGroupActivity_legacy_group_too_large, FeatureFlags.groupLimits().hardLimit - 1) - groupInfoText.setLearnMoreVisible(false) - } State.MMS_WARNING -> { groupInfoText.setText(R.string.ManageGroupActivity_this_is_an_insecure_mms_group) groupInfoText.setOnLinkClickListener { model.onMmsWarningClick() } @@ -63,8 +52,6 @@ object LegacyGroupPreference { enum class State { LEARN_MORE, - UPGRADE, - TOO_LARGE, MMS_WARNING, NONE } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationOptionsMenu.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationOptionsMenu.kt index 0421355246..cf42752538 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationOptionsMenu.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationOptionsMenu.kt @@ -16,7 +16,6 @@ import io.reactivex.rxjava3.kotlin.subscribeBy import org.signal.core.util.concurrent.LifecycleDisposable import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.R -import org.thoughtcrime.securesms.database.ThreadTable import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.recipients.Recipient @@ -119,14 +118,6 @@ internal object ConversationOptionsMenu { } } menuInflater.inflate(R.menu.conversation_group_options, menu) - if (!recipient.isPushGroup) { - menuInflater.inflate(R.menu.conversation_mms_group_options, menu) - if (distributionType == ThreadTable.DistributionTypes.BROADCAST) { - menu.findItem(R.id.menu_distribution_broadcast).isChecked = true - } else { - menu.findItem(R.id.menu_distribution_conversation).isChecked = true - } - } menuInflater.inflate(R.menu.conversation_active_group_options, menu) } @@ -216,8 +207,6 @@ internal object ConversationOptionsMenu { R.id.menu_search -> callback.handleSearch() R.id.menu_add_to_contacts -> callback.handleAddToContacts() R.id.menu_group_recipients -> callback.handleDisplayGroupRecipients() - R.id.menu_distribution_broadcast -> callback.handleDistributionBroadcastEnabled(menuItem) - R.id.menu_distribution_conversation -> callback.handleDistributionConversationEnabled(menuItem) R.id.menu_group_settings -> callback.handleManageGroup() R.id.menu_leave -> callback.handleLeavePushGroup() R.id.menu_invite -> callback.handleInviteLink() @@ -283,8 +272,6 @@ internal object ConversationOptionsMenu { fun handleSearch() fun handleAddToContacts() fun handleDisplayGroupRecipients() - fun handleDistributionBroadcastEnabled(menuItem: MenuItem) - fun handleDistributionConversationEnabled(menuItem: MenuItem) fun handleManageGroup() fun handleLeavePushGroup() fun handleInviteLink() 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 efc242e930..01c2272cef 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 @@ -219,7 +219,6 @@ import org.thoughtcrime.securesms.groups.ui.invitesandrequests.ManagePendingAndR import org.thoughtcrime.securesms.groups.ui.invitesandrequests.invite.GroupLinkInviteFriendsBottomSheetDialogFragment import org.thoughtcrime.securesms.groups.ui.managegroup.dialogs.GroupDescriptionDialog import org.thoughtcrime.securesms.groups.ui.migration.GroupsV1MigrationInfoBottomSheetDialogFragment -import org.thoughtcrime.securesms.groups.ui.migration.GroupsV1MigrationInitiationBottomSheetDialogFragment import org.thoughtcrime.securesms.groups.ui.migration.GroupsV1MigrationSuggestionsDialog import org.thoughtcrime.securesms.groups.v2.GroupBlockJoinRequestResult import org.thoughtcrime.securesms.invites.InviteActions @@ -3144,10 +3143,6 @@ class ConversationFragment : GroupMembersDialog(requireActivity(), recipientSnapshot).display() } - override fun handleDistributionBroadcastEnabled(menuItem: MenuItem) = error("This fragment does not support this action.") - - override fun handleDistributionConversationEnabled(menuItem: MenuItem) = error("This fragment does not support this action.") - override fun handleManageGroup() { val recipient = viewModel.recipientSnapshot ?: return val intent = ConversationSettingsActivity.forGroup(requireContext(), recipient.requireGroupId()) @@ -3612,16 +3607,6 @@ class ConversationFragment : } } - override fun onGroupV1MigrationClicked() { - val recipient = viewModel.recipientSnapshot - if (recipient == null) { - Log.w(TAG, "[onGroupV1MigrationClicked] No recipient!") - return - } - - GroupsV1MigrationInitiationBottomSheetDialogFragment.showForInitiation(childFragmentManager, recipient.id) - } - override fun onInviteToSignal(recipient: Recipient) { InviteActions.inviteUserToSignal( context = requireContext(), diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/DisabledInputView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/DisabledInputView.kt index 446f30baa0..3acc0d5c9f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/DisabledInputView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/DisabledInputView.kt @@ -87,7 +87,6 @@ class DisabledInputView @JvmOverloads constructor( setDeleteOnClickListener { listener?.onDeleteGroupClicked() } setBlockOnClickListener { listener?.onBlockClicked() } setUnblockOnClickListener { listener?.onUnblockClicked() } - setGroupV1MigrationContinueListener { listener?.onGroupV1MigrationClicked() } } ) } @@ -230,7 +229,6 @@ class DisabledInputView @JvmOverloads constructor( fun onDeleteGroupClicked() fun onBlockClicked() fun onUnblockClicked() - fun onGroupV1MigrationClicked() fun onInviteToSignal(recipient: Recipient) fun onUnmuteReleaseNotesChannel() } 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 0ccb08d10c..2b42772317 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/GroupTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/GroupTable.kt @@ -44,7 +44,6 @@ import org.thoughtcrime.securesms.groups.BadGroupIdException import org.thoughtcrime.securesms.groups.GroupId import org.thoughtcrime.securesms.groups.GroupId.Push import org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange -import org.thoughtcrime.securesms.groups.GroupsV1MigratedCache import org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob import org.thoughtcrime.securesms.keyvalue.SignalStore @@ -658,15 +657,9 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT @JvmOverloads @CheckReturnValue - fun create(groupMasterKey: GroupMasterKey, groupState: DecryptedGroup, force: Boolean = false): GroupId.V2? { + fun create(groupMasterKey: GroupMasterKey, groupState: DecryptedGroup): GroupId.V2? { val groupId = GroupId.v2(groupMasterKey) - if (!force && GroupsV1MigratedCache.hasV1Group(groupId)) { - throw MissedGroupMigrationInsertException(groupId) - } else if (force) { - Log.w(TAG, "Forcing the creation of a group even though we already have a V1 ID!") - } - return if (create(groupId = groupId, title = groupState.title, memberCollection = emptyList(), avatar = null, groupMasterKey = groupMasterKey, groupState = groupState)) { groupId } else { @@ -680,9 +673,6 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT */ fun fixMissingMasterKey(groupMasterKey: GroupMasterKey) { val groupId = GroupId.v2(groupMasterKey) - if (GroupsV1MigratedCache.hasV1Group(groupId)) { - Log.w(TAG, "There already exists a V1 group that should be migrated into this group. But if the recipient already exists, there's not much we can do here.") - } writableDatabase.withinTransaction { db -> val updated = db @@ -697,8 +687,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT groupMasterKey, DecryptedGroup.Builder() .revision(GroupsV2StateProcessor.RESTORE_PLACEHOLDER_REVISION) - .build(), - true + .build() ) } else { Log.w(TAG, "Had a group entry, but it was missing a master key. Updated.") @@ -1526,5 +1515,4 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT } class LegacyGroupInsertException(id: GroupId?) : IllegalStateException("Tried to create a new GV1 entry when we already had a migrated GV2! $id") - class MissedGroupMigrationInsertException(id: GroupId?) : IllegalStateException("Tried to create a new GV2 entry when we already had a V1 group that mapped to the new ID! $id") } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt index aa2f2e0436..0e22a73cd5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt @@ -56,7 +56,6 @@ import org.thoughtcrime.securesms.conversation.colors.ChatColors.Id.Companion.fo import org.thoughtcrime.securesms.conversation.colors.ChatColorsMapper.getChatColors import org.thoughtcrime.securesms.crypto.ProfileKeyUtil import org.thoughtcrime.securesms.database.GroupTable.LegacyGroupInsertException -import org.thoughtcrime.securesms.database.GroupTable.MissedGroupMigrationInsertException import org.thoughtcrime.securesms.database.GroupTable.ShowAsStoryState import org.thoughtcrime.securesms.database.IdentityTable.VerifiedStatus import org.thoughtcrime.securesms.database.SignalDatabase.Companion.groups @@ -80,7 +79,6 @@ import org.thoughtcrime.securesms.groups.BadGroupIdException import org.thoughtcrime.securesms.groups.GroupId import org.thoughtcrime.securesms.groups.GroupId.V1 import org.thoughtcrime.securesms.groups.GroupId.V2 -import org.thoughtcrime.securesms.groups.GroupsV1MigratedCache import org.thoughtcrime.securesms.groups.v2.ProfileKeySet import org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob @@ -574,8 +572,6 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da return existing.get() } else if (groupId.isV1 && groups.groupExists(groupId.requireV1().deriveV2MigrationGroupId())) { throw LegacyGroupInsertException(groupId) - } else if (groupId.isV2 && GroupsV1MigratedCache.hasV1Group(groupId.requireV2())) { - throw MissedGroupMigrationInsertException(groupId) } else { val values = ContentValues().apply { put(GROUP_ID, groupId.toString()) @@ -589,8 +585,6 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da return existing.get() } else if (groupId.isV1 && groups.groupExists(groupId.requireV1().deriveV2MigrationGroupId())) { throw LegacyGroupInsertException(groupId) - } else if (groupId.isV2 && groups.getGroupV1ByExpectedV2(groupId.requireV2()).isPresent) { - throw MissedGroupMigrationInsertException(groupId) } else { throw AssertionError("Failed to insert recipient!") } @@ -644,14 +638,6 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da } } - if (groupId.isV2) { - val v1 = GroupsV1MigratedCache.getV1GroupByV2Id(groupId.requireV2()) - if (v1 != null) { - db.setTransactionSuccessful() - return v1.recipientId - } - } - val id = getOrInsertFromGroupId(groupId) db.setTransactionSuccessful() return id 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 e47087aab2..6e51f4fdad 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 @@ -5,9 +5,9 @@ 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.database.RecipientTable import org.thoughtcrime.securesms.groups.GroupAccessControl import org.thoughtcrime.securesms.groups.GroupId -import org.thoughtcrime.securesms.groups.GroupsV1MigrationUtil import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId @@ -134,7 +134,7 @@ class GroupRecord( unmigratedV1Members .filterNot { members.contains(it) } .map { Recipient.resolved(it) } - .filter { GroupsV1MigrationUtil.isAutoMigratable(it) } + .filter { it.isAutoMigratable() } .map { it.id } } } @@ -181,4 +181,13 @@ class GroupRecord( } return false } + + companion object { + /** + * True if the user meets all the requirements to be auto-migrated, otherwise false. + */ + private fun Recipient.isAutoMigratable(): Boolean { + return hasServiceId() && registered === RecipientTable.RegisteredState.REGISTERED && profileKey != null + } + } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2.java index f2fbaef745..2da1d90b40 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2.java @@ -937,13 +937,6 @@ final class GroupManagerV2 { alreadyAMember = true; } - GroupRecord unmigratedV1Group = GroupsV1MigratedCache.getV1GroupByV2Id(groupId); - - if (unmigratedV1Group != null) { - Log.i(TAG, "Group link was for a migrated V1 group we know about! Migrating it and using that as the base."); - GroupsV1MigrationUtil.performLocalMigration(context, unmigratedV1Group.getId().requireV1()); - } - DecryptedGroup decryptedGroup = createPlaceholderGroup(joinInfo, requestToJoin); Optional group = groupDatabase.getGroup(groupId); diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigratedCache.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigratedCache.kt deleted file mode 100644 index c825895d70..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigratedCache.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2023 Signal Messenger, LLC - * SPDX-License-Identifier: AGPL-3.0-only - */ - -package org.thoughtcrime.securesms.groups - -import androidx.annotation.WorkerThread -import org.signal.core.util.orNull -import org.thoughtcrime.securesms.database.SignalDatabase -import org.thoughtcrime.securesms.database.model.GroupRecord -import org.thoughtcrime.securesms.util.LRUCache - -/** - * Cache to keep track of groups we know do not need a migration run on. This is to save time looking for a gv1 group - * with the expected v2 id. - */ -object GroupsV1MigratedCache { - private const val MAX_CACHE = 1000 - - private val noV1GroupCache = LRUCache(MAX_CACHE) - - @JvmStatic - @WorkerThread - fun hasV1Group(groupId: GroupId.V2): Boolean { - return getV1GroupByV2Id(groupId) != null - } - - @JvmStatic - @WorkerThread - fun getV1GroupByV2Id(groupId: GroupId.V2): GroupRecord? { - synchronized(noV1GroupCache) { - if (noV1GroupCache.containsKey(groupId)) { - return null - } - } - - val v1Group = SignalDatabase.groups.getGroupV1ByExpectedV2(groupId) - if (!v1Group.isPresent) { - synchronized(noV1GroupCache) { - noV1GroupCache.put(groupId, true) - } - } - return v1Group.orNull() - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigrationUtil.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigrationUtil.java deleted file mode 100644 index 1abaa3b111..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigrationUtil.java +++ /dev/null @@ -1,216 +0,0 @@ -package org.thoughtcrime.securesms.groups; - -import android.content.Context; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.annimon.stream.Stream; - -import org.signal.core.util.logging.Log; -import org.signal.libsignal.zkgroup.groups.GroupMasterKey; -import org.signal.storageservice.protos.groups.local.DecryptedGroup; -import org.thoughtcrime.securesms.database.GroupTable; -import org.thoughtcrime.securesms.database.RecipientTable; -import org.thoughtcrime.securesms.database.SignalDatabase; -import org.thoughtcrime.securesms.keyvalue.SignalStore; -import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.recipients.RecipientUtil; -import org.thoughtcrime.securesms.transport.RetryLaterException; -import org.thoughtcrime.securesms.util.FeatureFlags; - -import java.io.Closeable; -import java.io.IOException; -import java.util.List; - -import static org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor.LATEST; - -public final class GroupsV1MigrationUtil { - - private static final String TAG = Log.tag(GroupsV1MigrationUtil.class); - - private GroupsV1MigrationUtil() {} - - public static void migrate(@NonNull Context context, @NonNull RecipientId recipientId, boolean forced) - throws IOException, RetryLaterException, GroupChangeBusyException, InvalidMigrationStateException - { - Recipient groupRecipient = Recipient.resolved(recipientId); - Long threadId = SignalDatabase.threads().getThreadIdFor(recipientId); - GroupTable groupDatabase = SignalDatabase.groups(); - - if (threadId == null) { - Log.w(TAG, "No thread found!"); - throw new InvalidMigrationStateException(); - } - - if (!groupRecipient.isPushV1Group()) { - Log.w(TAG, "Not a V1 group!"); - throw new InvalidMigrationStateException(); - } - - if (groupRecipient.getParticipantIds().size() > FeatureFlags.groupLimits().getHardLimit()) { - Log.w(TAG, "Too many members! Size: " + groupRecipient.getParticipantIds().size()); - throw new InvalidMigrationStateException(); - } - - GroupId.V1 gv1Id = groupRecipient.requireGroupId().requireV1(); - GroupId.V2 gv2Id = gv1Id.deriveV2MigrationGroupId(); - GroupMasterKey gv2MasterKey = gv1Id.deriveV2MigrationMasterKey(); - boolean newlyCreated = false; - - if (groupDatabase.groupExists(gv2Id)) { - Log.w(TAG, "We already have a V2 group for this V1 group! Must have been added before we were migration-capable."); - throw new InvalidMigrationStateException(); - } - - if (!groupRecipient.isActiveGroup()) { - Log.w(TAG, "Group is inactive! Can't migrate."); - throw new InvalidMigrationStateException(); - } - - switch (GroupManager.v2GroupStatus(context, SignalStore.account().requireAci(), gv2MasterKey)) { - case DOES_NOT_EXIST: - Log.i(TAG, "Group does not exist on the service."); - - if (!groupRecipient.isProfileSharing()) { - Log.w(TAG, "Profile sharing is disabled! Can't migrate."); - throw new InvalidMigrationStateException(); - } - - List registeredMembers = RecipientUtil.getEligibleForSending(Recipient.resolvedList(groupRecipient.getParticipantIds())); - - if (RecipientUtil.ensureUuidsAreAvailable(context, registeredMembers)) { - Log.i(TAG, "Newly-discovered UUIDs. Getting fresh recipients."); - registeredMembers = Stream.of(registeredMembers).map(Recipient::fresh).toList(); - } - - List possibleMembers = forced ? registeredMembers - : getMigratableAutoMigrationMembers(registeredMembers); - - if (!forced && !groupRecipient.hasName()) { - Log.w(TAG, "Group has no name. Skipping auto-migration."); - throw new InvalidMigrationStateException(); - } - - if (!forced && possibleMembers.size() != registeredMembers.size()) { - Log.w(TAG, "Not allowed to invite or leave registered users behind in an auto-migration! Skipping."); - throw new InvalidMigrationStateException(); - } - - Log.i(TAG, "Attempting to create group."); - - try { - GroupManager.migrateGroupToServer(context, gv1Id, possibleMembers); - newlyCreated = true; - Log.i(TAG, "Successfully created!"); - } catch (GroupChangeFailedException e) { - Log.w(TAG, "Failed to migrate group. Retrying.", e); - throw new RetryLaterException(); - } catch (MembershipNotSuitableForV2Exception e) { - Log.w(TAG, "Failed to migrate job due to the membership not yet being suitable for GV2. Aborting.", e); - return; - } catch (GroupAlreadyExistsException e) { - Log.w(TAG, "Someone else created the group while we were trying to do the same! It exists now. Continuing on.", e); - } - break; - case NOT_A_MEMBER: - Log.w(TAG, "The migrated group already exists, but we are not a member. Doing a local leave."); - handleLeftBehind(gv1Id); - return; - case FULL_OR_PENDING_MEMBER: - Log.w(TAG, "The migrated group already exists, and we're in it. Continuing on."); - break; - default: throw new AssertionError(); - } - - Log.i(TAG, "Migrating local group " + gv1Id + " to " + gv2Id); - - DecryptedGroup decryptedGroup = performLocalMigration(context, gv1Id, threadId, groupRecipient); - - if (newlyCreated && decryptedGroup != null) { - Log.i(TAG, "Sending no-op update to notify others."); - GroupManager.sendNoopUpdate(context, gv2MasterKey, decryptedGroup); - } - } - - public static void performLocalMigration(@NonNull Context context, @NonNull GroupId.V1 gv1Id) throws IOException - { - Log.i(TAG, "Beginning local migration! V1 ID: " + gv1Id, new Throwable()); - try (Closeable ignored = GroupsV2ProcessingLock.acquireGroupProcessingLock(1000)) { - if (SignalDatabase.groups().groupExists(gv1Id.deriveV2MigrationGroupId())) { - Log.w(TAG, "Group was already migrated! Could have been waiting for the lock.", new Throwable()); - return; - } - - Recipient recipient = Recipient.externalGroupExact(gv1Id); - long threadId = SignalDatabase.threads().getOrCreateThreadIdFor(recipient); - - performLocalMigration(context, gv1Id, threadId, recipient); - Log.i(TAG, "Migration complete! (" + gv1Id + ", " + threadId + ", " + recipient.getId() + ")", new Throwable()); - } catch (GroupChangeBusyException e) { - throw new IOException(e); - } - } - - private static @Nullable DecryptedGroup performLocalMigration(@NonNull Context context, - @NonNull GroupId.V1 gv1Id, - long threadId, - @NonNull Recipient groupRecipient) - throws IOException, GroupChangeBusyException - { - Log.i(TAG, "performLocalMigration(" + gv1Id + ", " + threadId + ", " + groupRecipient.getId()); - - try (Closeable ignored = GroupsV2ProcessingLock.acquireGroupProcessingLock()){ - DecryptedGroup decryptedGroup; - try { - decryptedGroup = GroupManager.addedGroupVersion(SignalStore.account().requireAci(), context, gv1Id.deriveV2MigrationMasterKey()); - } catch (GroupDoesNotExistException e) { - throw new IOException("[Local] The group should exist already!"); - } catch (GroupNotAMemberException e) { - Log.w(TAG, "[Local] We are not in the group. Doing a local leave."); - handleLeftBehind(gv1Id); - return null; - } - - Log.i(TAG, "[Local] Migrating group over to the version we were added to: V" + decryptedGroup.revision); - SignalDatabase.groups().migrateToV2(threadId, gv1Id, decryptedGroup); - - Log.i(TAG, "[Local] Applying all changes since V" + decryptedGroup.revision); - try { - GroupManager.updateGroupFromServer(context, gv1Id.deriveV2MigrationMasterKey(), LATEST, System.currentTimeMillis(), null); - } catch (GroupChangeBusyException | GroupNotAMemberException e) { - Log.w(TAG, e); - } - - return decryptedGroup; - } - } - - private static void handleLeftBehind(@NonNull GroupId.V1 gv1Id) { - SignalDatabase.groups().setActive(gv1Id, false); - SignalDatabase.groups().remove(gv1Id, Recipient.self().getId()); - } - - /** - * In addition to meeting traditional requirements, you must also have a profile key for a member - * to consider them migratable in an auto-migration. - */ - private static @NonNull List getMigratableAutoMigrationMembers(@NonNull List registeredMembers) { - return Stream.of(registeredMembers) - .filter(r -> r.getProfileKey() != null) - .toList(); - } - - /** - * True if the user meets all the requirements to be auto-migrated, otherwise false. - */ - public static boolean isAutoMigratable(@NonNull Recipient recipient) { - return recipient.hasServiceId() && - recipient.getRegistered() == RecipientTable.RegisteredState.REGISTERED && - recipient.getProfileKey() != null; - } - - public static final class InvalidMigrationStateException extends Exception { - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationInfoBottomSheetDialogFragment.java b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationInfoBottomSheetDialogFragment.java index 9918affecf..9c02e18fa7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationInfoBottomSheetDialogFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationInfoBottomSheetDialogFragment.java @@ -25,8 +25,7 @@ import org.thoughtcrime.securesms.util.WindowUtil; import java.util.List; /** - * Shows more info about a GV1->GV2 migration event. Looks similar to - * {@link GroupsV1MigrationInitiationBottomSheetDialogFragment}, but only displays static data. + * Shows more info about a GV1->GV2 migration event. */ public final class GroupsV1MigrationInfoBottomSheetDialogFragment extends BottomSheetDialogFragment { diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationInitiationBottomSheetDialogFragment.java b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationInitiationBottomSheetDialogFragment.java deleted file mode 100644 index b54b9524a9..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationInitiationBottomSheetDialogFragment.java +++ /dev/null @@ -1,151 +0,0 @@ -package org.thoughtcrime.securesms.groups.ui.migration; - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AlertDialog; -import androidx.fragment.app.DialogFragment; -import androidx.fragment.app.FragmentManager; -import androidx.lifecycle.ViewModelProvider; - -import com.google.android.material.bottomsheet.BottomSheetDialogFragment; - -import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.groups.ui.GroupMemberListView; -import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.util.BottomSheetUtil; -import org.thoughtcrime.securesms.util.ThemeUtil; -import org.thoughtcrime.securesms.util.WindowUtil; -import org.thoughtcrime.securesms.util.views.SimpleProgressDialog; - -/** - * A bottom sheet that allows a user to initiation a manual GV1->GV2 migration. Will show the user - * the members that will be invited/left behind. - */ -public final class GroupsV1MigrationInitiationBottomSheetDialogFragment extends BottomSheetDialogFragment { - - private static final String KEY_GROUP_RECIPIENT_ID = "group_recipient_id"; - - private GroupsV1MigrationInitiationViewModel viewModel; - private GroupMemberListView inviteList; - private TextView inviteTitle; - private View inviteContainer; - private GroupMemberListView ineligibleList; - private TextView ineligibleTitle; - private View ineligibleContainer; - private View upgradeButton; - private View spinner; - - public static void showForInitiation(@NonNull FragmentManager manager, @NonNull RecipientId groupRecipientId) { - Bundle args = new Bundle(); - args.putParcelable(KEY_GROUP_RECIPIENT_ID, groupRecipientId); - - GroupsV1MigrationInitiationBottomSheetDialogFragment fragment = new GroupsV1MigrationInitiationBottomSheetDialogFragment(); - fragment.setArguments(args); - - fragment.show(manager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG); - } - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - setStyle(DialogFragment.STYLE_NORMAL, - ThemeUtil.isDarkTheme(requireContext()) ? R.style.Theme_Signal_RoundedBottomSheet - : R.style.Theme_Signal_RoundedBottomSheet_Light); - - super.onCreate(savedInstanceState); - } - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.groupsv1_migration_bottom_sheet, container, false); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - this.inviteContainer = view.findViewById(R.id.gv1_migrate_invite_container); - this.inviteTitle = view.findViewById(R.id.gv1_migrate_invite_title); - this.inviteList = view.findViewById(R.id.gv1_migrate_invite_list); - this.ineligibleContainer = view.findViewById(R.id.gv1_migrate_ineligible_container); - this.ineligibleTitle = view.findViewById(R.id.gv1_migrate_ineligible_title); - this.ineligibleList = view.findViewById(R.id.gv1_migrate_ineligible_list); - this.upgradeButton = view.findViewById(R.id.gv1_migrate_upgrade_button); - this.spinner = view.findViewById(R.id.gv1_migrate_spinner); - - inviteList.initializeAdapter(getViewLifecycleOwner()); - ineligibleList.initializeAdapter(getViewLifecycleOwner()); - - inviteList.setNestedScrollingEnabled(false); - ineligibleList.setNestedScrollingEnabled(false); - - //noinspection ConstantConditions - RecipientId groupRecipientId = getArguments().getParcelable(KEY_GROUP_RECIPIENT_ID); - - //noinspection ConstantConditions - viewModel = new ViewModelProvider(this, new GroupsV1MigrationInitiationViewModel.Factory(groupRecipientId)).get(GroupsV1MigrationInitiationViewModel.class); - viewModel.getMigrationState().observe(getViewLifecycleOwner(), this::onMigrationStateChanged); - - upgradeButton.setEnabled(false); - upgradeButton.setOnClickListener(v -> onUpgradeClicked()); - view.findViewById(R.id.gv1_migrate_cancel_button).setOnClickListener(v -> dismiss()); - } - - @Override - public void onResume() { - super.onResume(); - WindowUtil.initializeScreenshotSecurity(requireContext(), requireDialog().getWindow()); - } - - @Override - public void show(@NonNull FragmentManager manager, @Nullable String tag) { - BottomSheetUtil.show(manager, tag, this); - } - - private void onMigrationStateChanged(@NonNull MigrationState migrationState) { - if (migrationState.getNeedsInvite().size() > 0) { - inviteContainer.setVisibility(View.VISIBLE); - inviteTitle.setText(getResources().getQuantityText(R.plurals.GroupsV1MigrationInitiation_these_members_will_need_to_accept_an_invite, migrationState.getNeedsInvite().size())); - inviteList.setDisplayOnlyMembers(migrationState.getNeedsInvite()); - } else { - inviteContainer.setVisibility(View.GONE); - } - - if (migrationState.getIneligible().size() > 0) { - ineligibleContainer.setVisibility(View.VISIBLE); - ineligibleTitle.setText(getResources().getQuantityText(R.plurals.GroupsV1MigrationInitiation_these_members_are_not_capable_of_joining_new_groups, migrationState.getIneligible().size())); - ineligibleList.setDisplayOnlyMembers(migrationState.getIneligible()); - } else { - ineligibleContainer.setVisibility(View.GONE); - } - - upgradeButton.setEnabled(true); - spinner.setVisibility(View.GONE); - } - - private void onUpgradeClicked() { - AlertDialog dialog = SimpleProgressDialog.show(requireContext()); - viewModel.onUpgradeClicked().observe(getViewLifecycleOwner(), result -> { - switch (result) { - case SUCCESS: - dismiss(); - break; - case FAILURE_GENERAL: - Toast.makeText(requireContext(), R.string.GroupsV1MigrationInitiation_failed_to_upgrade, Toast.LENGTH_SHORT).show(); - dismiss(); - break; - case FAILURE_NETWORK: - Toast.makeText(requireContext(), R.string.GroupsV1MigrationInitiation_encountered_a_network_error, Toast.LENGTH_SHORT).show(); - dismiss(); - break; - default: - throw new IllegalStateException(); - } - dialog.dismiss(); - }); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationInitiationViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationInitiationViewModel.java deleted file mode 100644 index 72d25fb79a..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationInitiationViewModel.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.thoughtcrime.securesms.groups.ui.migration; - -import androidx.annotation.NonNull; -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; -import androidx.lifecycle.ViewModelProvider; - -import org.thoughtcrime.securesms.recipients.RecipientId; - -class GroupsV1MigrationInitiationViewModel extends ViewModel { - - private final RecipientId groupRecipientId; - private final MutableLiveData migrationState; - private final GroupsV1MigrationRepository repository; - - private GroupsV1MigrationInitiationViewModel(@NonNull RecipientId groupRecipientId) { - this.groupRecipientId = groupRecipientId; - this.migrationState = new MutableLiveData<>(); - this.repository = new GroupsV1MigrationRepository(); - - repository.getMigrationState(groupRecipientId, migrationState::postValue); - } - - @NonNull LiveData getMigrationState() { - return migrationState; - } - - @NonNull LiveData onUpgradeClicked() { - MutableLiveData migrationResult = new MutableLiveData<>(); - - repository.upgradeGroup(groupRecipientId, migrationResult::postValue); - - return migrationResult; - } - - static class Factory extends ViewModelProvider.NewInstanceFactory { - - private final RecipientId groupRecipientId; - - Factory(@NonNull RecipientId groupRecipientId) { - this.groupRecipientId = groupRecipientId; - } - - @Override - public @NonNull T create(@NonNull Class modelClass) { - return modelClass.cast(new GroupsV1MigrationInitiationViewModel(groupRecipientId)); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationRepository.java b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationRepository.java deleted file mode 100644 index 6d7cbe0b11..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationRepository.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.thoughtcrime.securesms.groups.ui.migration; - -import androidx.annotation.NonNull; -import androidx.annotation.WorkerThread; -import androidx.core.util.Consumer; - -import com.annimon.stream.Stream; - -import org.signal.core.util.concurrent.SignalExecutors; -import org.signal.core.util.logging.Log; -import org.thoughtcrime.securesms.database.RecipientTable; -import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; -import org.thoughtcrime.securesms.groups.GroupChangeBusyException; -import org.thoughtcrime.securesms.groups.GroupsV1MigrationUtil; -import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; -import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.recipients.RecipientUtil; -import org.thoughtcrime.securesms.transport.RetryLaterException; - -import java.io.IOException; -import java.util.Collections; -import java.util.List; - -final class GroupsV1MigrationRepository { - - private static final String TAG = Log.tag(GroupsV1MigrationRepository.class); - - void getMigrationState(@NonNull RecipientId groupRecipientId, @NonNull Consumer callback) { - SignalExecutors.BOUNDED.execute(() -> callback.accept(getMigrationState(groupRecipientId))); - } - - void upgradeGroup(@NonNull RecipientId recipientId, @NonNull Consumer callback) { - SignalExecutors.UNBOUNDED.execute(() -> { - if (!NetworkConstraint.isMet(ApplicationDependencies.getApplication())) { - Log.w(TAG, "No network!"); - callback.accept(MigrationResult.FAILURE_NETWORK); - return; - } - - if (!Recipient.resolved(recipientId).isPushV1Group()) { - Log.w(TAG, "Not a V1 group!"); - callback.accept(MigrationResult.FAILURE_GENERAL); - return; - } - - try { - GroupsV1MigrationUtil.migrate(ApplicationDependencies.getApplication(), recipientId, true); - callback.accept(MigrationResult.SUCCESS); - } catch (IOException | RetryLaterException | GroupChangeBusyException e) { - callback.accept(MigrationResult.FAILURE_NETWORK); - } catch (GroupsV1MigrationUtil.InvalidMigrationStateException e) { - callback.accept(MigrationResult.FAILURE_GENERAL); - } - }); - } - - @WorkerThread - private MigrationState getMigrationState(@NonNull RecipientId groupRecipientId) { - Recipient group = Recipient.resolved(groupRecipientId); - - if (!group.isPushV1Group()) { - return new MigrationState(Collections.emptyList(), Collections.emptyList()); - } - - List members = Recipient.resolvedList(group.getParticipantIds()); - - try { - List registered = Stream.of(members) - .filter(Recipient::isRegistered) - .toList(); - - RecipientUtil.ensureUuidsAreAvailable(ApplicationDependencies.getApplication(), registered); - } catch (IOException e) { - Log.w(TAG, "Failed to refresh UUIDs!", e); - } - - group = group.fresh(); - - List ineligible = Stream.of(members) - .filter(r -> !r.hasServiceId() || r.getRegistered() != RecipientTable.RegisteredState.REGISTERED) - .toList(); - - List invites = Stream.of(members) - .filterNot(ineligible::contains) - .filterNot(Recipient::isSelf) - .filter(r -> r.getProfileKey() == null) - .toList(); - - return new MigrationState(invites, ineligible); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/MigrationResult.java b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/MigrationResult.java deleted file mode 100644 index 47efa2d7ab..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/MigrationResult.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.thoughtcrime.securesms.groups.ui.migration; - -enum MigrationResult { - SUCCESS, FAILURE_GENERAL, FAILURE_NETWORK -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/MigrationState.java b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/MigrationState.java deleted file mode 100644 index f9ffee857e..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/MigrationState.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.thoughtcrime.securesms.groups.ui.migration; - -import androidx.annotation.NonNull; - -import org.thoughtcrime.securesms.recipients.Recipient; - -import java.util.List; - -/** - * Represents the migration state of a group. Namely, which users will be invited or left behind. - */ -final class MigrationState { - private final List needsInvite; - private final List ineligible; - - MigrationState(@NonNull List needsInvite, - @NonNull List ineligible) - { - this.needsInvite = needsInvite; - this.ineligible = ineligible; - } - - public @NonNull List getNeedsInvite() { - return needsInvite; - } - - public @NonNull List getIneligible() { - return ineligible; - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/GroupV1MigrationJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/GroupV1MigrationJob.java deleted file mode 100644 index d86e6fb5fb..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/GroupV1MigrationJob.java +++ /dev/null @@ -1,103 +0,0 @@ -package org.thoughtcrime.securesms.jobs; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import org.signal.core.util.concurrent.SignalExecutors; -import org.signal.core.util.logging.Log; -import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; -import org.thoughtcrime.securesms.groups.GroupChangeBusyException; -import org.thoughtcrime.securesms.groups.GroupsV1MigrationUtil; -import org.thoughtcrime.securesms.jobmanager.JsonJobData; -import org.thoughtcrime.securesms.jobmanager.Job; -import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; -import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.transport.RetryLaterException; -import org.whispersystems.signalservice.api.groupsv2.NoCredentialForRedemptionTimeException; -import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; - -public class GroupV1MigrationJob extends BaseJob { - - private static final String TAG = Log.tag(GroupV1MigrationJob.class); - - public static final String KEY = "GroupV1MigrationJob"; - - private static final String KEY_RECIPIENT_ID = "recipient_id"; - - private static final int ROUTINE_LIMIT = 20; - private static final long REFRESH_INTERVAL = TimeUnit.HOURS.toMillis(1); - - private final RecipientId recipientId; - - private GroupV1MigrationJob(@NonNull RecipientId recipientId) { - this(new Parameters.Builder() - .setQueue(recipientId.toQueueKey()) - .setMaxAttempts(Parameters.UNLIMITED) - .setLifespan(TimeUnit.DAYS.toMillis(7)) - .addConstraint(NetworkConstraint.KEY) - .build(), - recipientId); - } - - private GroupV1MigrationJob(@NonNull Parameters parameters, @NonNull RecipientId recipientId) { - super(parameters); - this.recipientId = recipientId; - } - - public static void enqueuePossibleAutoMigrate(@NonNull RecipientId recipientId) { - SignalExecutors.BOUNDED.execute(() -> { - if (Recipient.resolved(recipientId).isPushV1Group()) { - ApplicationDependencies.getJobManager().add(new GroupV1MigrationJob(recipientId)); - } - }); - } - - @Override - public @Nullable byte[] serialize() { - return new JsonJobData.Builder().putString(KEY_RECIPIENT_ID, recipientId.serialize()) - .serialize(); - } - - @Override - public @NonNull String getFactoryKey() { - return KEY; - } - - @Override - protected void onRun() throws IOException, GroupChangeBusyException, RetryLaterException { - if (Recipient.resolved(recipientId).isBlocked()) { - Log.i(TAG, "Group blocked. Skipping."); - return; - } - - try { - GroupsV1MigrationUtil.migrate(context, recipientId, false); - } catch (GroupsV1MigrationUtil.InvalidMigrationStateException e) { - Log.w(TAG, "Invalid migration state. Skipping."); - } - } - - @Override - protected boolean onShouldRetry(@NonNull Exception e) { - return e instanceof PushNetworkException || - e instanceof NoCredentialForRedemptionTimeException || - e instanceof GroupChangeBusyException || - e instanceof RetryLaterException; - } - - @Override - public void onFailure() { - } - - public static final class Factory implements Job.Factory { - @Override - public @NonNull GroupV1MigrationJob create(@NonNull Parameters parameters, @Nullable byte[] serializedData) { - JsonJobData data = JsonJobData.deserialize(serializedData); - return new GroupV1MigrationJob(parameters, RecipientId.from(data.getString(KEY_RECIPIENT_ID))); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java index c0672f8e90..db66574f78 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java @@ -124,7 +124,6 @@ public final class JobManagerFactories { put(ForceUpdateGroupV2WorkerJob.KEY, new ForceUpdateGroupV2WorkerJob.Factory()); put(GenerateAudioWaveFormJob.KEY, new GenerateAudioWaveFormJob.Factory()); put(GiftSendJob.KEY, new GiftSendJob.Factory()); - put(GroupV1MigrationJob.KEY, new GroupV1MigrationJob.Factory()); put(GroupCallUpdateSendJob.KEY, new GroupCallUpdateSendJob.Factory()); put(GroupCallPeekJob.KEY, new GroupCallPeekJob.Factory()); put(GroupCallPeekWorkerJob.KEY, new GroupCallPeekWorkerJob.Factory()); @@ -305,6 +304,7 @@ public final class JobManagerFactories { put("MmsDownloadJob", new FailingJob.Factory()); put("SmsReceiveJob", new FailingJob.Factory()); put("StoryReadStateMigrationJob", new PassingMigrationJob.Factory()); + put("GroupV1MigrationJob", new FailingJob.Factory()); }}; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushProcessMessageJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushProcessMessageJob.kt index d183ecd189..d172d5082b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushProcessMessageJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushProcessMessageJob.kt @@ -6,7 +6,6 @@ import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.database.SignalDatabase.Companion.groups import org.thoughtcrime.securesms.dependencies.ApplicationDependencies import org.thoughtcrime.securesms.groups.GroupChangeBusyException -import org.thoughtcrime.securesms.groups.GroupsV1MigratedCache import org.thoughtcrime.securesms.jobmanager.Job import org.thoughtcrime.securesms.jobmanager.impl.ChangeNumberConstraint import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint @@ -122,7 +121,7 @@ class PushProcessMessageJob private constructor( if (groupId.isV2) { val localRevision = groups.getGroupV2Revision(groupId.requireV2()) - if (groupContext.revision!! > localRevision || GroupsV1MigratedCache.hasV1Group(groupId)) { + if (groupContext.revision!! > localRevision) { Log.i(TAG, "Adding network constraint to group-related job.") requireNetwork = true } diff --git a/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestRepository.java b/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestRepository.java index 8c7f9f740c..ad7a91c6ef 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestRepository.java @@ -126,21 +126,17 @@ public final class MessageRequestRepository { } } else if (!RecipientUtil.isLegacyProfileSharingAccepted(recipient) && isLegacyThread(recipient)) { if (recipient.isGroup()) { - return MessageRequestState.LEGACY_GROUP_V1; + return MessageRequestState.DEPRECATED_GROUP_V1; } else { return MessageRequestState.LEGACY_INDIVIDUAL; } } else if (recipient.isPushV1Group()) { if (RecipientUtil.isMessageRequestAccepted(context, threadId)) { - if (recipient.getParticipantIds().size() > FeatureFlags.groupLimits().getHardLimit()) { - return MessageRequestState.DEPRECATED_GROUP_V1_TOO_LARGE; - } else { - return MessageRequestState.DEPRECATED_GROUP_V1; - } + return MessageRequestState.DEPRECATED_GROUP_V1; } else if (!recipient.isActiveGroup()) { return MessageRequestState.NONE; } else { - return MessageRequestState.GROUP_V1; + return MessageRequestState.DEPRECATED_GROUP_V1; } } else { if (RecipientUtil.isMessageRequestAccepted(context, threadId)) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestState.java b/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestState.java index 4451754b85..72de0689ec 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestState.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestState.java @@ -19,18 +19,9 @@ public enum MessageRequestState { /** An individual conversation that existed pre-message-requests but doesn't have profile sharing enabled */ LEGACY_INDIVIDUAL, - /** A V1 group conversation that existed pre-message-requests but doesn't have profile sharing enabled */ - LEGACY_GROUP_V1, - /** A V1 group conversation that is no longer allowed, because we've forced GV2 on. */ DEPRECATED_GROUP_V1, - /** A V1 group conversation that is no longer allowed, because we've forced GV2 on, but it's also too large to migrate. Nothing we can do. */ - DEPRECATED_GROUP_V1_TOO_LARGE, - - /** A message request is needed for a V1 group */ - GROUP_V1, - /** An invite response is needed for a V2 group */ GROUP_V2_INVITE, diff --git a/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestsBottomView.java b/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestsBottomView.java index b5fd1f0289..d21b3075ea 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestsBottomView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestsBottomView.java @@ -4,9 +4,9 @@ import android.content.Context; import android.content.res.ColorStateList; import android.util.AttributeSet; import android.view.View; -import android.widget.Button; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.Group; import androidx.core.text.HtmlCompat; @@ -17,7 +17,6 @@ import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.CommunicationActions; import org.thoughtcrime.securesms.util.Debouncer; -import org.thoughtcrime.securesms.util.FeatureFlags; import org.thoughtcrime.securesms.util.HtmlUtil; import org.thoughtcrime.securesms.util.views.LearnMoreTextView; @@ -29,7 +28,6 @@ public class MessageRequestsBottomView extends ConstraintLayout { private LearnMoreTextView question; private MaterialButton accept; - private MaterialButton gv1Continue; private MaterialButton block; private MaterialButton delete; private MaterialButton bigDelete; @@ -38,8 +36,7 @@ public class MessageRequestsBottomView extends ConstraintLayout { private Group normalButtons; private Group blockedButtons; - private Group gv1MigrationButtons; - private Group activeGroup; + private @Nullable Group activeGroup; public MessageRequestsBottomView(Context context) { super(context); @@ -66,10 +63,8 @@ public class MessageRequestsBottomView extends ConstraintLayout { delete = findViewById(R.id.message_request_delete); bigDelete = findViewById(R.id.message_request_big_delete); bigUnblock = findViewById(R.id.message_request_big_unblock); - gv1Continue = findViewById(R.id.message_request_gv1_migration); normalButtons = findViewById(R.id.message_request_normal_buttons); blockedButtons = findViewById(R.id.message_request_blocked_buttons); - gv1MigrationButtons = findViewById(R.id.message_request_gv1_migration_buttons); busyIndicator = findViewById(R.id.message_request_busy_indicator); setWallpaperEnabled(false); @@ -89,67 +84,49 @@ public class MessageRequestsBottomView extends ConstraintLayout { question.setText(HtmlCompat.fromHtml(getContext().getString(message, HtmlUtil.bold(recipient.getShortDisplayName(getContext()))), 0)); - setActiveInactiveGroups(blockedButtons, normalButtons, gv1MigrationButtons); + setActiveInactiveGroups(blockedButtons, normalButtons); break; case BLOCKED_GROUP: question.setText(R.string.MessageRequestBottomView_unblock_this_group_and_share_your_name_and_photo_with_its_members); - setActiveInactiveGroups(blockedButtons, normalButtons, gv1MigrationButtons); + setActiveInactiveGroups(blockedButtons, normalButtons); break; case LEGACY_INDIVIDUAL: question.setText(getContext().getString(R.string.MessageRequestBottomView_continue_your_conversation_with_s_and_share_your_name_and_photo, recipient.getShortDisplayName(getContext()))); question.setLearnMoreVisible(true); question.setOnLinkClickListener(v -> CommunicationActions.openBrowserLink(getContext(), getContext().getString(R.string.MessageRequestBottomView_legacy_learn_more_url))); - setActiveInactiveGroups(normalButtons, blockedButtons, gv1MigrationButtons); - accept.setText(R.string.MessageRequestBottomView_continue); - break; - case LEGACY_GROUP_V1: - question.setText(R.string.MessageRequestBottomView_continue_your_conversation_with_this_group_and_share_your_name_and_photo); - question.setLearnMoreVisible(true); - question.setOnLinkClickListener(v -> CommunicationActions.openBrowserLink(getContext(), getContext().getString(R.string.MessageRequestBottomView_legacy_learn_more_url))); - setActiveInactiveGroups(normalButtons, blockedButtons, gv1MigrationButtons); + setActiveInactiveGroups(normalButtons, blockedButtons); accept.setText(R.string.MessageRequestBottomView_continue); break; case DEPRECATED_GROUP_V1: question.setText(R.string.MessageRequestBottomView_upgrade_this_group_to_activate_new_features); - setActiveInactiveGroups(gv1MigrationButtons, normalButtons, blockedButtons); - gv1Continue.setVisibility(VISIBLE); - break; - case DEPRECATED_GROUP_V1_TOO_LARGE: - question.setText(getContext().getString(R.string.MessageRequestBottomView_this_legacy_group_can_no_longer_be_used, FeatureFlags.groupLimits().getHardLimit() - 1)); - setActiveInactiveGroups(gv1MigrationButtons, normalButtons, blockedButtons); - gv1Continue.setVisibility(GONE); - break; - case GROUP_V1: - question.setText(R.string.MessageRequestBottomView_do_you_want_to_join_this_group_they_wont_know_youve_seen_their_messages_until_you_accept); - setActiveInactiveGroups(normalButtons, blockedButtons, gv1MigrationButtons); - accept.setText(R.string.MessageRequestBottomView_accept); + setActiveInactiveGroups(null, normalButtons, blockedButtons); break; case GROUP_V2_INVITE: question.setText(R.string.MessageRequestBottomView_do_you_want_to_join_this_group_you_wont_see_their_messages); - setActiveInactiveGroups(normalButtons, blockedButtons, gv1MigrationButtons); + setActiveInactiveGroups(normalButtons, blockedButtons); accept.setText(R.string.MessageRequestBottomView_accept); break; case GROUP_V2_ADD: question.setText(R.string.MessageRequestBottomView_join_this_group_they_wont_know_youve_seen_their_messages_until_you_accept); - setActiveInactiveGroups(normalButtons, blockedButtons, gv1MigrationButtons); + setActiveInactiveGroups(normalButtons, blockedButtons); accept.setText(R.string.MessageRequestBottomView_accept); break; case INDIVIDUAL: question.setText(HtmlCompat.fromHtml(getContext().getString(R.string.MessageRequestBottomView_do_you_want_to_let_s_message_you_they_wont_know_youve_seen_their_messages_until_you_accept, HtmlUtil.bold(recipient.getShortDisplayName(getContext()))), 0)); - setActiveInactiveGroups(normalButtons, blockedButtons, gv1MigrationButtons); + setActiveInactiveGroups(normalButtons, blockedButtons); accept.setText(R.string.MessageRequestBottomView_accept); break; case INDIVIDUAL_HIDDEN: question.setText(HtmlCompat.fromHtml(getContext().getString(R.string.MessageRequestBottomView_do_you_want_to_let_s_message_you_you_removed_them_before, HtmlUtil.bold(recipient.getShortDisplayName(getContext()))), 0)); - setActiveInactiveGroups(normalButtons, blockedButtons, gv1MigrationButtons); + setActiveInactiveGroups(normalButtons, blockedButtons); accept.setText(R.string.MessageRequestBottomView_accept); break; } } - private void setActiveInactiveGroups(@NonNull Group activeGroup, @NonNull Group... inActiveGroups) { + private void setActiveInactiveGroups(@Nullable Group activeGroup, @NonNull Group... inActiveGroups) { int initialVisibility = this.activeGroup != null ? this.activeGroup.getVisibility() : VISIBLE; this.activeGroup = activeGroup; @@ -158,7 +135,9 @@ public class MessageRequestsBottomView extends ConstraintLayout { inactive.setVisibility(GONE); } - activeGroup.setVisibility(initialVisibility); + if (activeGroup != null) { + activeGroup.setVisibility(initialVisibility); + } } public void showBusy() { @@ -179,7 +158,7 @@ public class MessageRequestsBottomView extends ConstraintLayout { public void setWallpaperEnabled(boolean isEnabled) { MessageRequestBarColorTheme theme = MessageRequestBarColorTheme.resolveTheme(isEnabled); - Stream.of(delete, bigDelete, block, bigUnblock, accept, gv1Continue).forEach(button -> { + Stream.of(delete, bigDelete, block, bigUnblock, accept).forEach(button -> { button.setBackgroundTintList(ColorStateList.valueOf(theme.getButtonBackgroundColor(getContext()))); }); @@ -187,7 +166,7 @@ public class MessageRequestsBottomView extends ConstraintLayout { button.setTextColor(theme.getButtonForegroundDenyColor(getContext())); }); - Stream.of(accept, bigUnblock, gv1Continue).forEach(button -> { + Stream.of(accept, bigUnblock).forEach(button -> { button.setTextColor(theme.getButtonForegroundAcceptColor(getContext())); }); @@ -210,8 +189,4 @@ public class MessageRequestsBottomView extends ConstraintLayout { public void setUnblockOnClickListener(OnClickListener unblockOnClickListener) { bigUnblock.setOnClickListener(unblockOnClickListener); } - - public void setGroupV1MigrationContinueListener(OnClickListener acceptOnClickListener) { - gv1Continue.setOnClickListener(acceptOnClickListener); - } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.kt index 3a02137865..f9f4c10560 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.kt @@ -20,8 +20,6 @@ import org.thoughtcrime.securesms.groups.GroupChangeBusyException import org.thoughtcrime.securesms.groups.GroupId import org.thoughtcrime.securesms.groups.GroupManager import org.thoughtcrime.securesms.groups.GroupNotAMemberException -import org.thoughtcrime.securesms.groups.GroupsV1MigratedCache -import org.thoughtcrime.securesms.groups.GroupsV1MigrationUtil import org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor import org.thoughtcrime.securesms.jobs.AutomaticSessionResetJob import org.thoughtcrime.securesms.jobs.NullMessageSendJob @@ -232,10 +230,6 @@ open class MessageContentProcessor(private val context: Context) { senderRecipient: Recipient, groupSecretParams: GroupSecretParams? = null ): Gv2PreProcessResult { - val v1Group = GroupsV1MigratedCache.getV1GroupByV2Id(groupId) - if (v1Group != null) { - GroupsV1MigrationUtil.performLocalMigration(context, v1Group.id.requireV1()) - } val preUpdateGroupRecord = SignalDatabase.groups.getGroup(groupId) val groupUpdateResult = updateGv2GroupFromServerOrP2PChange(context, timestamp, groupV2, preUpdateGroupRecord, groupSecretParams) if (groupUpdateResult == null) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/storage/GroupV2RecordProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/storage/GroupV2RecordProcessor.java index dedfcc1695..e76b1b9c5a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/storage/GroupV2RecordProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/storage/GroupV2RecordProcessor.java @@ -11,12 +11,10 @@ import org.thoughtcrime.securesms.database.GroupTable; import org.thoughtcrime.securesms.database.RecipientTable; import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.groups.GroupId; -import org.thoughtcrime.securesms.groups.GroupsV1MigrationUtil; import org.thoughtcrime.securesms.recipients.RecipientId; import org.whispersystems.signalservice.api.storage.SignalGroupV2Record; import org.whispersystems.signalservice.internal.storage.protos.GroupV2Record; -import java.io.IOException; import java.util.Arrays; import java.util.Map; import java.util.Optional; @@ -98,26 +96,9 @@ public final class GroupV2RecordProcessor extends DefaultStorageRecordProcessor< } } - /** - * This contains a pretty big compromise: In the event that the new GV2 group we learned about - * was, in fact, a migrated V1 group we already knew about, we handle the migration here. This - * isn't great because the migration will likely result in network activity. And because this is - * all happening in a transaction, this could keep the transaction open for longer than we'd like. - * However, given that nearly all V1 groups have already been migrated, we're at a point where - * this event should be extraordinarily rare, and it didn't seem worth it to add a lot of - * complexity to accommodate this specific scenario. - */ @Override - void insertLocal(@NonNull SignalGroupV2Record record) throws IOException { - GroupId.V2 actualV2Id = GroupId.v2(record.getMasterKeyOrThrow()); - GroupId.V1 possibleV1Id = gv1GroupsByExpectedGv2Id.get(actualV2Id); - - if (possibleV1Id != null) { - Log.i(TAG, "Discovered a new GV2 ID that is actually a migrated V1 group! Migrating now."); - GroupsV1MigrationUtil.performLocalMigration(context, possibleV1Id); - } else { - recipientTable.applyStorageSyncGroupV2Insert(record); - } + void insertLocal(@NonNull SignalGroupV2Record record) { + recipientTable.applyStorageSyncGroupV2Insert(record); } @Override diff --git a/app/src/main/res/layout/message_request_bottom_bar.xml b/app/src/main/res/layout/message_request_bottom_bar.xml index 1b0721eeb0..5b7eb20eba 100644 --- a/app/src/main/res/layout/message_request_bottom_bar.xml +++ b/app/src/main/res/layout/message_request_bottom_bar.xml @@ -66,19 +66,6 @@ app:layout_constraintStart_toEndOf="@+id/message_request_delete" app:layout_constraintTop_toTopOf="@id/message_request_block" /> - - + app:constraint_referenced_ids="message_request_block,message_request_big_delete" /> - - - - - - - - - - - - - - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index deb3746bb7..8e51c33230 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1535,7 +1535,7 @@ Let %1$s message you? You won\'t receive any messages until you unblock them. Get updates and news from %1$s? You won\'t receive any updates until you unblock them. Continue your chat with this group and share your name and photo with its members? - Upgrade this group to activate new features like @mentions and admins. Members who have not shared their name or photo in this group will be invited to join. + This Legacy Group can no longer be used. Create a new group to activate new features like @mentions and admins. This Legacy Group can no longer be used because it is too large. The maximum group size is %1$d. Continue your chat with %1$s and share your name and photo with them? Join this group and share your name and photo with its members? They won\'t know you\'ve seen their messages until you accept.