From 5193dfa41254bc1b5dfe2340371357edcfb50e9a Mon Sep 17 00:00:00 2001 From: adbenitez Date: Fri, 1 May 2026 15:38:06 +0200 Subject: [PATCH 1/9] allow to open message links via actions in TalkBack menu --- .../securesms/ConversationItem.java | 36 +++++++++++++++++++ src/main/res/values/strings.xml | 3 ++ 2 files changed, 39 insertions(+) diff --git a/src/main/java/org/thoughtcrime/securesms/ConversationItem.java b/src/main/java/org/thoughtcrime/securesms/ConversationItem.java index a3c6a0ba6..f58609b62 100644 --- a/src/main/java/org/thoughtcrime/securesms/ConversationItem.java +++ b/src/main/java/org/thoughtcrime/securesms/ConversationItem.java @@ -24,6 +24,7 @@ import android.graphics.PorterDuff; import android.graphics.Rect; import android.os.Build; import android.text.SpannableString; +import android.text.Spanned; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; @@ -36,6 +37,7 @@ import androidx.annotation.DimenRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; +import androidx.core.view.ViewCompat; import chat.delta.rpc.RpcException; import chat.delta.rpc.types.CallInfo; import chat.delta.rpc.types.CallState; @@ -44,6 +46,7 @@ import chat.delta.rpc.types.VcardContact; import com.b44t.messenger.DcChat; import com.b44t.messenger.DcContact; import com.b44t.messenger.DcMsg; +import java.util.ArrayList; import java.util.List; import java.util.Set; import org.thoughtcrime.securesms.calls.CallCoordinator; @@ -72,6 +75,7 @@ import org.thoughtcrime.securesms.mms.VcardSlide; import org.thoughtcrime.securesms.reactions.ReactionsConversationView; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.Linkifier; +import org.thoughtcrime.securesms.util.LongClickCopySpan; import org.thoughtcrime.securesms.util.LongClickMovementMethod; import org.thoughtcrime.securesms.util.MediaUtil; import org.thoughtcrime.securesms.util.Util; @@ -119,6 +123,9 @@ public class ConversationItem extends BaseConversationItem { private Stub callViewStub; private @Nullable EventListener eventListener; + // IDs of accessibility actions registered via ViewCompat.addAccessibilityAction + private final List linkActionIds = new ArrayList<>(); + private int measureCalls; private int incomingBubbleColor; @@ -423,6 +430,12 @@ public class ConversationItem extends BaseConversationItem { bodyText.setClickable(false); bodyText.setFocusable(false); + // Remove any link actions registered for the previous message binding + for (int id : linkActionIds) { + ViewCompat.removeAccessibilityAction(this, id); + } + linkActionIds.clear(); + String text = messageRecord.getText(); if (messageRecord.getType() == DcMsg.DC_MSG_CALL || text.isEmpty()) { @@ -434,6 +447,29 @@ public class ConversationItem extends BaseConversationItem { } bodyText.setText(spannable); bodyText.setVisibility(View.VISIBLE); + + // Register a TalkBack "Actions" entry for each link in the message + if (spannable instanceof Spanned) { + Spanned spanned = (Spanned) spannable; + final TextView tv = bodyText; + for (LongClickCopySpan span : + spanned.getSpans(0, spanned.length(), LongClickCopySpan.class)) { + int start = spanned.getSpanStart(span); + int end = spanned.getSpanEnd(span); + if (start >= 0 && end > start && end <= spanned.length()) { + String linkText = spanned.subSequence(start, end).toString(); + String label = context.getString(R.string.accessibility_link_action, linkText); + linkActionIds.add( + ViewCompat.addAccessibilityAction( + this, + label, + (v, args) -> { + span.onClick(tv); + return true; + })); + } + } + } } int downloadState = messageRecord.getDownloadState(); diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 4fbb496c6..710d39e34 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -1217,6 +1217,9 @@ Tap here to receive messages while Delta Chat is in the background. You already allowed Delta Chat to receive messages in the background.\n\nIf messages still do not arrive in background, please also check your system settings. + + Open %1$s + What\'s new?\n\n💯 End-to-end encryption is reliable and forever now. Padlocks 🔒 are gone!\n\n✉️ Classic email without end-to-end encryption is marked with a letter symbol\n\n😻 New enhanced profile screen for all your contacts\n\n🔲 New button for quick access to apps used in a chat\n\n❤️ Please donate to help us remain independent and continue to bring improvements: %1$s From 5d0e85b30dfba1dec64d548f34a0dfbf58204def Mon Sep 17 00:00:00 2001 From: adbenitez Date: Fri, 1 May 2026 15:41:06 +0200 Subject: [PATCH 2/9] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a7c1acf8..c8fd7a118 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * Mark chats as unread (long tap a chat and select the corresponding option from the three-dot-menu) * Fix process of upgrading from a very old version of the app * Show more recent added stickers at the top of the sticker picker +* Allow to open links in messages via actions in TalkBack menu ## v2.49.0 2026-04 From 2ab544b18e8c08e2f496bf6fa92c4bcd5de9a1b1 Mon Sep 17 00:00:00 2001 From: adbenitez Date: Mon, 4 May 2026 19:55:13 +0200 Subject: [PATCH 3/9] don't set draft if user can't send --- .../securesms/ConversationActivity.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java b/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java index 977e3f3b1..668f4dee8 100644 --- a/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java @@ -674,8 +674,14 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } public void setDraftText(String txt) { - composeText.setText(txt); - composeText.setSelection(composeText.getText().length()); + try { + if (rpc.canSend(rpc.getSelectedAccountId(), chatId)) { + composeText.setText(txt); + composeText.setSelection(composeText.getText().length()); + } + } catch (RpcException e) { + Log.e(TAG, "Rpc error", e); + } } public void hideSoftKeyboard() { @@ -1260,6 +1266,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity DcContext dcContext = DcHelper.getContext(context); final int currentChatId = dcChat.getId(); + final boolean canSend = dcChat.canSend(); Util.runOnAnyBackgroundThread( () -> { DcMsg msg = null; @@ -1378,7 +1385,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } } } else { - dcContext.setDraft(currentChatId, msg); + // set or clear draft if user can't send in chat since they can't delete it otherwise + dcContext.setDraft(currentChatId, canSend ? msg : null); } future.set(currentChatId); }); From 6a9c3ab8ca20958b3b078badcf2b0d9e444bf87f Mon Sep 17 00:00:00 2001 From: adbenitez Date: Mon, 4 May 2026 19:57:10 +0200 Subject: [PATCH 4/9] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9627a1f1..99b984b7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * Fix process of upgrading from a very old version of the app * Show more recent added stickers at the top of the sticker picker * Allow to open map if user clicks "Location streaming enabled" system message +* Fix: do not accidentally set draft in chats that don't allow sending messages ## v2.49.0 2026-04 From 2b36e2dc26196673eb6a07bf908de75258b52c2b Mon Sep 17 00:00:00 2001 From: wchen342 Date: Mon, 4 May 2026 14:02:37 -0400 Subject: [PATCH 5/9] Hide webxdc attach button for channels (#4402) --- .../java/org/thoughtcrime/securesms/ConversationActivity.java | 1 + .../securesms/components/AttachmentTypeSelector.java | 4 ++++ src/main/res/layout/attachment_type_selector.xml | 1 + 3 files changed, 6 insertions(+) diff --git a/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java b/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java index 977e3f3b1..acc19aa10 100644 --- a/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java @@ -1116,6 +1116,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity if (chatId == DcChat.DC_CHAT_NO_CHAT) throw new IllegalStateException("can't display a conversation for no chat."); dcChat = DcHelper.getContext(context).getChat(chatId); + attachmentTypeSelector = null; recipient = new Recipient(this, dcChat); glideRequests = GlideApp.with(this); diff --git a/src/main/java/org/thoughtcrime/securesms/components/AttachmentTypeSelector.java b/src/main/java/org/thoughtcrime/securesms/components/AttachmentTypeSelector.java index dc4112e70..6edafddbc 100644 --- a/src/main/java/org/thoughtcrime/securesms/components/AttachmentTypeSelector.java +++ b/src/main/java/org/thoughtcrime/securesms/components/AttachmentTypeSelector.java @@ -92,6 +92,10 @@ public class AttachmentTypeSelector extends PopupWindow { ViewUtil.findById(layout, R.id.location_linear_layout).setVisibility(View.GONE); } + if (DcHelper.getContext(context).getChat(chatId).isOutBroadcast()) { + ViewUtil.findById(layout, R.id.webxdc_linear_layout).setVisibility(View.GONE); + } + setLocationButtonImage(context); setContentView(layout); diff --git a/src/main/res/layout/attachment_type_selector.xml b/src/main/res/layout/attachment_type_selector.xml index a2ad90ce3..3b3aee145 100644 --- a/src/main/res/layout/attachment_type_selector.xml +++ b/src/main/res/layout/attachment_type_selector.xml @@ -203,6 +203,7 @@ Date: Mon, 4 May 2026 20:13:37 +0200 Subject: [PATCH 6/9] remove unnecessary check --- .../securesms/ConversationItem.java | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/thoughtcrime/securesms/ConversationItem.java b/src/main/java/org/thoughtcrime/securesms/ConversationItem.java index f58609b62..4ead84239 100644 --- a/src/main/java/org/thoughtcrime/securesms/ConversationItem.java +++ b/src/main/java/org/thoughtcrime/securesms/ConversationItem.java @@ -449,25 +449,23 @@ public class ConversationItem extends BaseConversationItem { bodyText.setVisibility(View.VISIBLE); // Register a TalkBack "Actions" entry for each link in the message - if (spannable instanceof Spanned) { - Spanned spanned = (Spanned) spannable; - final TextView tv = bodyText; - for (LongClickCopySpan span : - spanned.getSpans(0, spanned.length(), LongClickCopySpan.class)) { - int start = spanned.getSpanStart(span); - int end = spanned.getSpanEnd(span); - if (start >= 0 && end > start && end <= spanned.length()) { - String linkText = spanned.subSequence(start, end).toString(); - String label = context.getString(R.string.accessibility_link_action, linkText); - linkActionIds.add( - ViewCompat.addAccessibilityAction( - this, - label, - (v, args) -> { - span.onClick(tv); - return true; - })); - } + Spanned spanned = (Spanned) spannable; + final TextView tv = bodyText; + for (LongClickCopySpan span : + spanned.getSpans(0, spanned.length(), LongClickCopySpan.class)) { + int start = spanned.getSpanStart(span); + int end = spanned.getSpanEnd(span); + if (start >= 0 && end > start && end <= spanned.length()) { + String linkText = spanned.subSequence(start, end).toString(); + String label = context.getString(R.string.accessibility_link_action, linkText); + linkActionIds.add( + ViewCompat.addAccessibilityAction( + this, + label, + (v, args) -> { + span.onClick(tv); + return true; + })); } } } From 102c3fd82ad6adc5c365018884630d7045c774de Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 4 May 2026 10:37:35 +0200 Subject: [PATCH 7/9] make strings as deprecated --- src/main/res/values/strings.xml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 4fbb496c6..c35db54e5 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -814,16 +814,23 @@ Wallpaper Use Default Image Select From Gallery + If you change this option, make sure, your server and your other clients are configured accordingly.\n\nOtherwise things may not work at all. Multi-Device Mode Synchronize your messages with your other devices. Automatically enabled on adding a second device Multi-Device Mode must be enabled when using the same profile on multiple devices. Only disable this setting if you have removed this profile from all your other devices.\n\nDisabling Multi-Device Mode while using the profile on multiple devices will result in missed messages and other problems. + Move automatically to DeltaChat Folder + Only Fetch from DeltaChat Folder + Show Classic Emails + No, chats only + For accepted contacts + All Experimental Features These features may be unstable and may be changed or removed @@ -878,14 +885,17 @@ Delete Old Messages Delete Messages from Device + Delete Messages from Server Do you want to delete %1$d messages now and all newly fetched messages \"%2$s\" in the future?\n\n• This includes all media\n\n• Messages will be deleted whether they were seen or not\n\n• \"Saved messages\" will be skipped from local deletion - + Do you want to delete %1$d messages now and all newly fetched messages \"%2$s\" in the future?\n\n⚠️ This includes emails, media and \"Saved messages\" in all server folders\n\n⚠️ Do not use this function if you want to keep data on the server or if you use classic email clients as well - + This includes emails, media and \"Saved messages\" in all server folders. Do not use this function if you want to keep data on the server or if you use classic email clients as well + Turn on at-once deletion + If you enable at-once deletion you cannot use multiple devices on this profile. I understand, delete all these messages From e85ae5247ae72a6ad8afa39e45a24f4c42a7dea3 Mon Sep 17 00:00:00 2001 From: adbenitez Date: Tue, 5 May 2026 15:40:06 +0200 Subject: [PATCH 8/9] add "mark all as read" to account menu --- .../securesms/accounts/AccountSelectionListFragment.java | 6 ++++++ src/main/res/menu/account_item_context.xml | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/main/java/org/thoughtcrime/securesms/accounts/AccountSelectionListFragment.java b/src/main/java/org/thoughtcrime/securesms/accounts/AccountSelectionListFragment.java index 8098ef0ee..05893f499 100644 --- a/src/main/java/org/thoughtcrime/securesms/accounts/AccountSelectionListFragment.java +++ b/src/main/java/org/thoughtcrime/securesms/accounts/AccountSelectionListFragment.java @@ -157,6 +157,12 @@ public class AccountSelectionListFragment extends DialogFragment onSetTag(accountId); } else if (itemId == R.id.menu_move_to_top) { onMoveToTop(accountId); + } else if (itemId == R.id.menu_mark_all_as_read) { + try { + DcHelper.getRpc(requireActivity()).marknoticedAllChats(accountId); + } catch (RpcException e) { + Log.e(TAG, "Error calling rpc.marknoticedAllChats()", e); + } } } diff --git a/src/main/res/menu/account_item_context.xml b/src/main/res/menu/account_item_context.xml index 1fc476d11..165517152 100644 --- a/src/main/res/menu/account_item_context.xml +++ b/src/main/res/menu/account_item_context.xml @@ -2,6 +2,10 @@ + + From 82262cb1664944a52b5045a1200df612c58ee07d Mon Sep 17 00:00:00 2001 From: adbenitez Date: Tue, 5 May 2026 15:41:55 +0200 Subject: [PATCH 9/9] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00b7fbfce..52bb99220 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * Allow to share location for 24 hours * Allow mini-apps to play audio without user interaction * Mark chats as unread (long tap a chat and select the corresponding option from the three-dot-menu) +* Add "Mark all as read" option to profile menu in the profile switcher * Fix process of upgrading from a very old version of the app * Show more recent added stickers at the top of the sticker picker * Allow to open links in messages via actions in TalkBack menu