diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt index 7f526c518d..269234b169 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt @@ -1212,7 +1212,14 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe return false } return viewModel.recipient?.let { recipient -> - ConversationMenuHelper.onOptionItemSelected(this, item, recipient, configFactory, storage) + ConversationMenuHelper.onOptionItemSelected( + context = this, + item = item, + thread = recipient, + threadID = threadId, + factory = configFactory, + storage = storage + ) } ?: false } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt index 3593d211e1..11040cc8c0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt @@ -52,7 +52,7 @@ import org.thoughtcrime.securesms.showSessionDialog import org.thoughtcrime.securesms.util.BitmapUtil object ConversationMenuHelper { - + fun onPrepareOptionsMenu( menu: Menu, inflater: MenuInflater, @@ -152,6 +152,7 @@ object ConversationMenuHelper { context: Context, item: MenuItem, thread: Recipient, + threadID: Long, factory: ConfigFactory, storage: StorageProtocol ): Boolean { @@ -166,7 +167,7 @@ object ConversationMenuHelper { R.id.menu_copy_account_id -> { copyAccountID(context, thread) } R.id.menu_copy_open_group_url -> { copyOpenGroupUrl(context, thread) } R.id.menu_edit_group -> { editClosedGroup(context, thread) } - R.id.menu_leave_group -> { leaveClosedGroup(context, thread, factory, storage) } + R.id.menu_leave_group -> { leaveClosedGroup(context, thread, threadID, factory, storage) } R.id.menu_invite_to_open_group -> { inviteContacts(context, thread) } R.id.menu_unmute_notifications -> { unmute(context, thread) } R.id.menu_mute_notifications -> { mute(context, thread) } @@ -305,9 +306,10 @@ object ConversationMenuHelper { } } - private fun leaveClosedGroup( + fun leaveClosedGroup( context: Context, thread: Recipient, + threadID: Long, configFactory: ConfigFactory, storage: StorageProtocol ) { @@ -318,16 +320,23 @@ object ConversationMenuHelper { val accountID = TextSecurePreferences.getLocalNumber(context) val isCurrentUserAdmin = admins.any { it.toString() == accountID } - confirmAndLeaveClosedGroup(context, group.title, isCurrentUserAdmin, doLeave = { - val groupPublicKey = doubleDecodeGroupID(thread.address.toString()).toHexString() + confirmAndLeaveClosedGroup( + context = context, + groupName = group.title, + isAdmin = isCurrentUserAdmin, + threadID = threadID, + storage = storage, + doLeave = { + val groupPublicKey = doubleDecodeGroupID(thread.address.toString()).toHexString() - check(DatabaseComponent.get(context).lokiAPIDatabase().isClosedGroup(groupPublicKey)) { - "Invalid group public key" + check(DatabaseComponent.get(context).lokiAPIDatabase().isClosedGroup(groupPublicKey)) { + "Invalid group public key" + } + MessageSender.leave(groupPublicKey, notifyUser = false) } - MessageSender.leave(groupPublicKey, notifyUser = false) - }) + ) } - + thread.isClosedGroupV2Recipient -> { val accountId = AccountId(thread.address.serialize()) val group = configFactory.userGroups?.getClosedGroup(accountId.hexString) ?: return @@ -339,6 +348,8 @@ object ConversationMenuHelper { context = context, groupName = name, isAdmin = isAdmin, + threadID = threadID, + storage = storage, doLeave = { check(storage.leaveGroup(accountId.hexString, true)) } @@ -351,6 +362,8 @@ object ConversationMenuHelper { context: Context, groupName: String, isAdmin: Boolean, + threadID: Long, + storage: StorageProtocol, doLeave: () -> Unit, ) { val message = if (isAdmin) { @@ -375,6 +388,9 @@ object ConversationMenuHelper { text(message) dangerButton(R.string.leave) { try { + // Cancel any outstanding jobs + storage.cancelPendingMessageSendJobs(threadID) + doLeave() } catch (e: Exception) { onLeaveFailed() diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt index 1df32307e2..82c623f27a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -73,6 +73,7 @@ import org.thoughtcrime.securesms.home.search.GlobalSearchViewModel import org.thoughtcrime.securesms.messagerequests.MessageRequestsActivity import com.bumptech.glide.Glide import com.bumptech.glide.RequestManager +import org.thoughtcrime.securesms.conversation.v2.menus.ConversationMenuHelper import org.thoughtcrime.securesms.permissions.Permissions import org.thoughtcrime.securesms.preferences.SettingsActivity import org.thoughtcrime.securesms.recoverypassword.RecoveryPasswordActivity @@ -592,49 +593,46 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), private fun deleteConversation(thread: ThreadRecord) { val threadID = thread.threadId val recipient = thread.recipient + + if (recipient.isClosedGroupV2Recipient || recipient.isLegacyClosedGroupRecipient) { + ConversationMenuHelper.leaveClosedGroup( + context = this, + thread = recipient, + threadID = threadID, + configFactory = configFactory, + storage = storage + ) + + return + } + val title: String val message: CharSequence var positiveButtonId: Int = R.string.yes var negativeButtonId: Int = R.string.no - if (recipient.isGroupRecipient) { - val group = groupDatabase.getGroup(recipient.address.toString()).orNull() - - // If you are an admin of this group you can delete it - if (group != null && group.admins.map { it.toString() } - .contains(textSecurePreferences.getLocalNumber())) { - title = getString(R.string.groupLeave) - message = Phrase.from(this.applicationContext, R.string.groupDeleteDescription) - .put(GROUP_NAME_KEY, group.title) - .format() - } else { - // Otherwise this is either a community, or it's a group you're not an admin of - title = - if (recipient.isCommunityRecipient) getString(R.string.communityLeave) else getString( - R.string.groupLeave - ) - message = Phrase.from(this.applicationContext, R.string.groupLeaveDescription) - .put(GROUP_NAME_KEY, group.title) - .format() - } - - positiveButtonId = R.string.leave + if (recipient.isCommunityRecipient) { + title = + if (recipient.isCommunityRecipient) getString(R.string.communityLeave) else getString( + R.string.groupLeave + ) + message = Phrase.from(this.applicationContext, R.string.groupLeaveDescription) + .put(GROUP_NAME_KEY, recipient.name.orEmpty()) + .format() + } + // If this is a 1-on-1 conversation + else if (recipient.name != null) { + title = getString(R.string.conversationsDelete) + message = Phrase.from(this.applicationContext, R.string.conversationsDeleteDescription) + .put(NAME_KEY, recipient.name) + .format() + } + else { + // If not group-related and we don't have a recipient name then this must be our Note to Self conversation + title = getString(R.string.clearMessages) + message = getString(R.string.clearMessagesNoteToSelfDescription) + positiveButtonId = R.string.clear negativeButtonId = R.string.cancel - } else { - // If this is a 1-on-1 conversation - if (recipient.name != null) { - title = getString(R.string.conversationsDelete) - message = Phrase.from(this.applicationContext, R.string.conversationsDeleteDescription) - .put(NAME_KEY, recipient.name) - .format() - } - else { - // If not group-related and we don't have a recipient name then this must be our Note to Self conversation - title = getString(R.string.clearMessages) - message = getString(R.string.clearMessagesNoteToSelfDescription) - positiveButtonId = R.string.clear - negativeButtonId = R.string.cancel - } } showSessionDialog { @@ -646,23 +644,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), // Cancel any outstanding jobs DatabaseComponent.get(context).sessionJobDatabase() .cancelPendingMessageSendJobs(threadID) - // Send a leave group message if this is an active closed group - if (recipient.address.isLegacyClosedGroup && DatabaseComponent.get(context) - .groupDatabase().isActive(recipient.address.toGroupString()) - ) { - try { - GroupUtil.doubleDecodeGroupID(recipient.address.toString()) - .toHexString() - .takeIf(DatabaseComponent.get(context).lokiAPIDatabase()::isClosedGroup) - ?.let { MessageSender.explicitLeave(it, true, deleteThread = true) } - } catch (ioe: IOException) { - Log.w(TAG, "Got an IOException while sending leave group message", ioe) - } - } - if (recipient.address.isClosedGroupV2) { - val groupLeave = LibSessionGroupLeavingJob(AccountId(recipient.address.serialize()), true) - JobQueue.shared.add(groupLeave) - } + // Delete the conversation val v2OpenGroup = DatabaseComponent.get(context).lokiThreadDatabase() .getOpenGroupChat(threadID) @@ -672,7 +654,12 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), v2OpenGroup.room, context ) + } else { + lifecycleScope.launch(Dispatchers.IO) { + threadDb.deleteConversation(threadID) + } } + // Update the badge count ApplicationContext.getInstance(context).messageNotifier.updateNotification(context)