leave and delete (#4262)

* deleting groups/channels is available after leaving only

* update CHANGELOG

* Update src/main/java/org/thoughtcrime/securesms/ConversationActivity.java

Co-authored-by: adb <adb@merlinux.eu>

* mailing lists are not encrypted

---------

Co-authored-by: adb <adb@merlinux.eu>
This commit is contained in:
biörn
2026-03-11 00:40:04 +01:00
committed by GitHub
parent f95a6e8db7
commit 6949be6fd8
6 changed files with 42 additions and 13 deletions
+1
View File
@@ -6,6 +6,7 @@
* Unified date display in call bubbles
* Explain at "Settings / Chats / Outgoing Media Quality" how to send original quality
* Add a basic sticker picker
* Leave groups and channels before deletion
* Fix: keep original sent timestamp for resent messages
* Fix: make clicking on broadcast member-added messages work always
* Fix: remove notification when a message is deleted by sender
@@ -1,5 +1,7 @@
package com.b44t.messenger;
import org.thoughtcrime.securesms.util.Util;
public class DcChat {
public static final int DC_CHAT_TYPE_UNDEFINED = 0;
@@ -56,6 +58,16 @@ public class DcChat {
return type != DC_CHAT_TYPE_SINGLE;
}
public boolean shallLeaveBeforeDelete(DcContext dcContext) {
if (isInBroadcast()) {
final int[] members = dcContext.getChatContacts(getId());
return Util.contains(members, DcContact.DC_CONTACT_ID_SELF);
} else if (isMultiUser() && isEncrypted() && canSend() && !isOutBroadcast()) {
return true;
}
return false;
}
public boolean isMailingList() {
return getType() == DC_CHAT_TYPE_MAILINGLIST;
}
@@ -29,6 +29,7 @@ import androidx.core.graphics.drawable.IconCompat;
import androidx.fragment.app.Fragment;
import com.b44t.messenger.DcChat;
import com.b44t.messenger.DcContact;
import com.b44t.messenger.DcContext;
import com.google.android.material.snackbar.Snackbar;
@@ -267,11 +268,19 @@ public abstract class BaseConversationListFragment extends Fragment implements A
alertText = activity.getResources().getQuantityString(R.plurals.ask_delete_chat, chatsCount, chatsCount);
}
String alertButton = getString(R.string.delete_for_me);
for (long chatId : selectedChats) {
if (dcContext.getChat((int) chatId).shallLeaveBeforeDelete(dcContext)) {
alertButton = getString(R.string.menu_leave_and_delete);
break;
}
}
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
alert.setMessage(alertText);
alert.setCancelable(true);
alert.setPositiveButton(R.string.delete, (dialog, which) -> {
alert.setPositiveButton(alertButton, (dialog, which) -> {
if (!selectedChats.isEmpty()) {
new AsyncTask<Void, Void, Void>() {
@@ -290,6 +299,9 @@ public abstract class BaseConversationListFragment extends Fragment implements A
int accountId = dcContext.getAccountId();
for (long chatId : selectedChats) {
DcHelper.getNotificationCenter(requireContext()).removeNotifications(accountId, (int) chatId);
if (dcContext.getChat((int) chatId).shallLeaveBeforeDelete(dcContext)) {
dcContext.removeContactFromChat((int) chatId, DcContact.DC_CONTACT_ID_SELF);
}
dcContext.deleteChat((int) chatId);
DirectShareUtil.clearShortcut(requireContext(), (int) chatId);
}
@@ -528,15 +528,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
menu.findItem(R.id.menu_ephemeral_messages).setVisible(false);
}
if (isMultiUser()) {
if (dcChat.isInBroadcast() && !dcChat.isContactRequest()) {
menu.findItem(R.id.menu_leave).setTitle(R.string.menu_leave_channel).setVisible(true);
} else if (dcChat.isEncrypted()
&& dcChat.canSend()
&& !dcChat.isOutBroadcast()
&& !dcChat.isMailingList()) {
menu.findItem(R.id.menu_leave).setVisible(true);
if (dcChat.shallLeaveBeforeDelete(DcHelper.getContext(context))) {
if (dcChat.isInBroadcast()) {
menu.findItem(R.id.menu_leave).setTitle(R.string.menu_leave_channel);
}
menu.findItem(R.id.menu_leave).setVisible(true);
menu.findItem(R.id.menu_delete_chat).setVisible(false);
}
if (isArchived()) {
@@ -729,9 +726,15 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
DcHelper.getContext(context).removeContactFromChat(chatId, DcContact.DC_CONTACT_ID_SELF);
Toast.makeText(this, getString(R.string.done), Toast.LENGTH_SHORT).show();
})
.setNegativeButton(R.string.cancel, null)
.setNegativeButton(R.string.menu_leave_and_delete, (d, which) -> {
DcHelper.getContext(context).removeContactFromChat(chatId, DcContact.DC_CONTACT_ID_SELF);
DcHelper.getContext(context).deleteChat(chatId);
Toast.makeText(this, getString(R.string.done), Toast.LENGTH_SHORT).show();
})
.setNeutralButton(R.string.cancel, null)
.show();
Util.redPositiveButton(dialog);
Util.redButton(dialog, AlertDialog.BUTTON_NEGATIVE);
}
private void handleArchiveChat() {
+3 -3
View File
@@ -67,13 +67,13 @@
<item android:title="@string/menu_add_attachment"
android:id="@+id/menu_add_attachment" />
<item android:title="@string/clear_chat"
android:id="@+id/menu_clear_chat"/>
<item android:id="@+id/menu_leave"
android:visible="false"
android:title="@string/menu_leave_group"/>
<item android:title="@string/clear_chat"
android:id="@+id/menu_clear_chat"/>
<item android:title="@string/menu_delete_chat"
android:id="@+id/menu_delete_chat"/>
</menu>
+1
View File
@@ -281,6 +281,7 @@
<string name="menu_add_attachment">Add Attachment</string>
<string name="menu_leave_group">Leave Group</string>
<string name="menu_leave_channel">Leave Channel</string>
<string name="menu_leave_and_delete">Leave &amp; Delete for Me</string>
<string name="menu_delete_chat">Delete Chat</string>
<!-- Command to delete all messages in a chat. The chat itself will not be deleted but will be empty afterwards, so make sure to be different from "Delete Chat" here. "Clear" is a verb here, "Empty Chat" would also be fine (eg. in German "Chat leeren") -->
<string name="clear_chat">Clear Chat</string>